/* Copyright (c) 2018 The Johns Hopkins University/Applied Physics Laboratory
 * All Rights Reserved.
 *
 * This file is dual licensed under the terms of the Apache 2.0 License and
 * the BSD 3-Clause License. See the LICENSE file in the root of this
 * repository for more information.
 */

#include <stdio.h>
#include <string.h>
#include "kmip.h"



#define TEST_PASSED(A, B)       \
do                              \
{                               \
    printf("PASS - %s\n", (B)); \
    (A)->tests_passed++;        \
    return(0);                  \
} while(0)

#define TEST_FAILED(A, B, C)               \
do                                         \
{                                          \
    printf("FAIL - %s @ L%d\n", (B), (C)); \
    (A)->tests_failed++;                   \
    return(1);                             \
} while(0)

#define TRACK_TEST(A) ((A)->test_count++)


typedef struct test_tracker
{
    uint16 test_count;
    uint16 tests_failed;
    uint16 tests_passed;
} TestTracker;


int
report_encoding_test_result(
    TestTracker *tracker,
    struct kmip *ctx,
    const uint8 *expected,
    const uint8 *observed,
    int result,
    const char *function)
{
    if(result == KMIP_OK)
    {
        for(size_t i = 0; i < ctx->size; i++)
        {
            if(expected[i] != observed[i])
            {
                printf("FAIL - %s\n", function);
                printf("- byte mismatch at: %zu (exp: %X, obs: %X)\n",
                       i, expected[i], observed[i]);
                for(size_t j = 0; j < ctx->size; j++)
                {
                    printf("- %zu: %X - %X\n", j, expected[j], observed[j]);
                }
                tracker->tests_failed++;
                return(1);
            }
        }
        
        TEST_PASSED(tracker, function);
    }
    else
    {
        printf("FAIL - %s\n", function);
        if(result == KMIP_ERROR_BUFFER_FULL)
        {
            printf("- context buffer is full\n");
        }
        kmip_print_stack_trace(ctx);
        tracker->tests_failed++;
        return(1);
    }
}

int
report_decoding_test_result(
    TestTracker *tracker,
    struct kmip *ctx,
    int comparison,
    int result,
    const char *function)
{
    if(result == KMIP_OK)
    {
        if(comparison)
        {
            TEST_PASSED(tracker, function);
        }
        else
        {
            printf("FAIL - %s\n", function);
            printf("- compared objects are not identical\n");
            tracker->tests_failed++;
            return(1);
        }
    }
    else
    {
        printf("FAIL - %s\n", function);
        if(result == KMIP_ERROR_BUFFER_FULL)
        {
            printf("- context buffer is underfull\n");
        }
        kmip_print_stack_trace(ctx);
        tracker->tests_failed++;
        return(1);
    }
}

int
report_result(TestTracker *tracker, int observed, int expected, const char *function)
{
    if(observed == expected)
    {
        TEST_PASSED(tracker, function);
    }
    else
    {
        printf("FAIL - %s\n", function);
        tracker->tests_failed++;
        return(1);
    }
}

int
test_linked_list_push(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    LinkedList list = {0};

    LinkedListItem a = {0};
    LinkedListItem b = {0};
    LinkedListItem c = {0};

    if(list.head != NULL || list.tail != NULL || list.size != 0)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_linked_list_push(&list, &a);

    if(list.head != &a || list.tail != &a || list.size != 1)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_linked_list_push(&list, &b);

    if(list.head != &b || list.tail != &a || list.size != 2)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_linked_list_push(&list, &c);

    if(list.head != &c || list.tail != &a || list.size != 3)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    LinkedListItem *curr = list.head;
    if(curr != &c || curr->next != &b || curr->prev != NULL)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    curr = curr->next;
    if(curr != &b || curr->next != &a || curr->prev != &c)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    curr = curr->next;
    if(curr != &a || curr->next != NULL || curr->prev != &b)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    TEST_PASSED(tracker, __func__);
}

int
test_linked_list_pop(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    LinkedList list = {0};

    if(list.head != NULL || list.tail != NULL || list.size != 0)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    LinkedListItem *item = kmip_linked_list_pop(&list);

    if(item != NULL || list.head != NULL || list.tail != NULL || list.size != 0)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    LinkedListItem a = {0};
    LinkedListItem b = {0};
    LinkedListItem c = {0};

    a.next = &b;
    a.prev = NULL;
    b.next = &c;
    b.prev = &a;
    c.next = NULL;
    c.prev = &b;

    list.head = &a;
    list.tail = &c;
    list.size = 3;

    item = kmip_linked_list_pop(&list);

    if(item != &a || list.head != &b || list.tail != &c || list.size != 2)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    item = kmip_linked_list_pop(&list);

    if(item != &b || list.head != &c || list.tail != &c || list.size != 1)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    item = kmip_linked_list_pop(&list);

    if(item != &c || list.head != NULL || list.tail != NULL || list.size != 0)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    TEST_PASSED(tracker, __func__);
}

int
test_linked_list_enqueue(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    LinkedList list = {0};

    LinkedListItem a = {0};
    LinkedListItem b = {0};
    LinkedListItem c = {0};

    if(list.head != NULL || list.tail != NULL || list.size != 0)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_linked_list_enqueue(&list, &a);

    if(list.head != &a || list.tail != &a || list.size != 1)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_linked_list_enqueue(&list, &b);

    if(list.head != &a || list.tail != &b || list.size != 2)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_linked_list_enqueue(&list, &c);

    if(list.head != &a || list.tail != &c || list.size != 3)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    LinkedListItem *curr = list.head;
    if(curr != &a || curr->next != &b || curr->prev != NULL)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    curr = curr->next;
    if(curr != &b || curr->next != &c || curr->prev != &a)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    curr = curr->next;
    if(curr != &c || curr->next != NULL || curr->prev != &b)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    TEST_PASSED(tracker, __func__);
}

int
test_buffer_full_and_resize(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[40] = {
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 too_small[30] = {0};
    uint8 large_enough[40] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, too_small, ARRAY_LENGTH(too_small), KMIP_1_0);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    int result = kmip_encode_protocol_version(&ctx, &pv);
    
    if(result == KMIP_ERROR_BUFFER_FULL)
    {
        kmip_reset(&ctx);
        kmip_set_buffer(&ctx, large_enough, ARRAY_LENGTH(large_enough));
        
        result = kmip_encode_protocol_version(&ctx, &pv);
        result = report_encoding_test_result(
            tracker,
            &ctx,
            expected,
            large_enough,
            result,
            __func__);
        
        kmip_destroy(&ctx);
        
        return(result);
    }
    else
    {
        printf("FAIL - %s\n", __func__);
        printf("- expected buffer full\n");
        
        kmip_destroy(&ctx);
        tracker->tests_failed++;
        return(1);
    }
}

int
test_is_tag_next(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[3] = {0x42, 0x00, 0x08};
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 *before = ctx.index;
    int result = 0;
    
    if(kmip_is_tag_next(&ctx, KMIP_TAG_ATTRIBUTE) == KMIP_FALSE)
    {
        printf("FAIL - %s\n", __func__);
        printf("- expected tag is not next\n");
        tracker->tests_failed++;
        result = 1;
    }
    
    uint8 *after = ctx.index;
    
    if(before != after)
    {
        printf("FAIL - %s\n", __func__);
        printf("- tag checking modifies context buffer index\n");
        tracker->tests_failed++;
        result = 1;
    }
    
    kmip_destroy(&ctx);
    
    if(result == 0)
    {
        printf("PASS - %s\n", __func__);
        tracker->tests_passed++;
    }
    
    return(result);
}

int
test_get_num_items_next(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[168] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x17, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x6C, 
        0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x14, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x4C, 0x65, 
        0x6E, 0x67, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x55, 0x73, 
        0x61, 0x67, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x6B, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00        
    };

    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 *before = ctx.index;
    int result = 0;
    int count = 0;
    
    count = kmip_get_num_items_next(&ctx, KMIP_TAG_ATTRIBUTE);
    if(count != 3)
    {
        printf("FAIL - %s\n", __func__);
        printf("- expected item count not found (exp. 3, obs. %d)\n",
               count);
        tracker->tests_failed++;
        result = 1;
    }
    
    uint8 *after = ctx.index;
    
    if(before != after)
    {
        printf("FAIL - %s\n", __func__);
        printf("- item count checking modifies context buffer index\n");
        tracker->tests_failed++;
        result = 1;
    }
    
    kmip_destroy(&ctx);
    
    if(result == 0)
    {
        printf("PASS - %s\n", __func__);
        tracker->tests_passed++;
    }
    
    return(result);
}

int
test_get_num_items_next_with_partial_item(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[136] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x14, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x4C, 0x65, 
        0x6E, 0x67, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x55, 0x73, 
        0x61, 0x67, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x6B, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72 
    };

    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 *before = ctx.index;
    int result = 0;
    int count = 0;
    
    count = kmip_get_num_items_next(&ctx, KMIP_TAG_ATTRIBUTE);
    if(count != 2)
    {
        printf("FAIL - %s\n", __func__);
        printf("- expected item count not found (exp. 2, obs. %d)\n",
               count);
        tracker->tests_failed++;
        result = 1;
    }
    
    uint8 *after = ctx.index;
    
    if(before != after)
    {
        printf("FAIL - %s\n", __func__);
        printf("- item count checking modifies context buffer index\n");
        tracker->tests_failed++;
        result = 1;
    }
    
    kmip_destroy(&ctx);
    
    if(result == 0)
    {
        printf("PASS - %s\n", __func__);
        tracker->tests_passed++;
    }
    
    return(result);
}

int
test_get_num_items_next_with_mismatch_item(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[80] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x55, 0x73, 
        0x61, 0x67, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x6B, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72 
    };

    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 *before = ctx.index;
    int result = 0;
    int count = 0;
    
    count = kmip_get_num_items_next(&ctx, KMIP_TAG_ATTRIBUTE);
    if(count != 1)
    {
        printf("FAIL - %s\n", __func__);
        printf("- expected item count not found (exp. 1, obs. %d)\n",
               count);
        tracker->tests_failed++;
        result = 1;
    }
    
    uint8 *after = ctx.index;
    
    if(before != after)
    {
        printf("FAIL - %s\n", __func__);
        printf("- item count checking modifies context buffer index\n");
        tracker->tests_failed++;
        result = 1;
    }
    
    kmip_destroy(&ctx);
    
    if(result == 0)
    {
        printf("PASS - %s\n", __func__);
        tracker->tests_passed++;
    }
    
    return(result);
}

int
test_get_num_items_next_with_no_matches(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[80] = {
        0x42, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x55, 0x73, 
        0x61, 0x67, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x6B, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72 
    };

    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 *before = ctx.index;
    int result = 0;
    int count = 0;
    
    count = kmip_get_num_items_next(&ctx, KMIP_TAG_ATTRIBUTE);
    if(count != 0)
    {
        printf("FAIL - %s\n", __func__);
        printf("- expected item count not found (exp. 0, obs. %d)\n",
               count);
        tracker->tests_failed++;
        result = 1;
    }
    
    uint8 *after = ctx.index;
    
    if(before != after)
    {
        printf("FAIL - %s\n", __func__);
        printf("- item count checking modifies context buffer index\n");
        tracker->tests_failed++;
        result = 1;
    }
    
    kmip_destroy(&ctx);
    
    if(result == 0)
    {
        printf("PASS - %s\n", __func__);
        tracker->tests_passed++;
    }
    
    return(result);
}

int
test_get_num_items_next_with_non_structures(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[144] = {
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x26,
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35, 
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D, 
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x11, 0x11, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x25,
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35, 
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D, 
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x11, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24,
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35, 
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D, 
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x00, 0x00, 0x00, 0x00
    };

    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 *before = ctx.index;
    int result = 0;
    int count = 0;
    
    count = kmip_get_num_items_next(&ctx, KMIP_TAG_UNIQUE_IDENTIFIER);
    if(count != 3)
    {
        printf("FAIL - %s\n", __func__);
        printf("- expected item count not found (exp. 3, obs. %d)\n",
               count);
        tracker->tests_failed++;
        result = 1;
    }
    
    uint8 *after = ctx.index;
    
    if(before != after)
    {
        printf("FAIL - %s\n", __func__);
        printf("- item count checking modifies context buffer index\n");
        tracker->tests_failed++;
        result = 1;
    }
    
    kmip_destroy(&ctx);
    
    if(result == 0)
    {
        printf("PASS - %s\n", __func__);
        tracker->tests_passed++;
    }
    
    return(result);
}

int
test_buffer_bytes_left(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 a[1] = {0x42};
    uint8 b[3] = {0x42, 0x00, 0x08};
    uint8 c[5] = {0x42, 0x00, 0x53, 0x01, 0x00};

    KMIP ctx = {0};
    kmip_init(&ctx, a, ARRAY_LENGTH(a), KMIP_1_0);

    if(BUFFER_BYTES_LEFT(&ctx) != 1)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_destroy(&ctx);
    kmip_init(&ctx, b, ARRAY_LENGTH(b), KMIP_1_0);

    if(BUFFER_BYTES_LEFT(&ctx) != 3)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_destroy(&ctx);
    kmip_init(&ctx, c, ARRAY_LENGTH(c), KMIP_1_0);

    if(BUFFER_BYTES_LEFT(&ctx) != 5)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_destroy(&ctx);

    TEST_PASSED(tracker, __func__);
}

int
test_get_num_attributes_next(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* Need to build an encoding with one of each type of support
       attribute. Verify that this function returns the correct
       count.

       Need to build an encoding with bad attribute length? Handle
       weird corner cases?
    */
    TEST_FAILED(tracker, __func__, __LINE__);
}

int
test_peek_tag(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* Build an encoding with an arbitrary tag value. Verify that this
       function reads and returns this tag value without changing the
       context buffer.
    */

    uint8 underfull_encoding[1] = {0x42};
    uint8 full_encoding[3] = {0x42, 0x00, 0x08};
    uint8 overfull_encoding[5] = {0x42, 0x00, 0x53, 0x01, 0x00};

    uint32 tag = 0;
    uint8 *prev_buffer = NULL;
    uint8 *prev_index = NULL;
    size_t prev_size = 0;
    KMIP ctx = {0};
    kmip_init(&ctx, underfull_encoding, ARRAY_LENGTH(underfull_encoding), KMIP_1_0);

    prev_buffer = ctx.buffer;
    prev_index = ctx.index;
    prev_size = ctx.size;
    tag = kmip_peek_tag(&ctx);
    if(tag != 0 || ctx.buffer != prev_buffer || ctx.index != prev_index || ctx.size != prev_size)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_destroy(&ctx);
    kmip_init(&ctx, full_encoding, ARRAY_LENGTH(full_encoding), KMIP_1_0);

    prev_buffer = ctx.buffer;
    prev_index = ctx.index;
    prev_size = ctx.size;
    tag = kmip_peek_tag(&ctx);
    if(tag != KMIP_TAG_ATTRIBUTE || ctx.buffer != prev_buffer || ctx.index != prev_index || ctx.size != prev_size)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_destroy(&ctx);
    kmip_init(&ctx, overfull_encoding, ARRAY_LENGTH(overfull_encoding), KMIP_1_0);

    prev_buffer = ctx.buffer;
    prev_index = ctx.index;
    prev_size = ctx.size;
    tag = kmip_peek_tag(&ctx);
    if(tag != KMIP_TAG_NAME || ctx.buffer != prev_buffer || ctx.index != prev_index || ctx.size != prev_size)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_destroy(&ctx);

    TEST_PASSED(tracker, __func__);
}

int
test_is_attribute_tag(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    if(!kmip_is_attribute_tag(KMIP_TAG_UNIQUE_IDENTIFIER))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_NAME))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_OBJECT_TYPE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_CRYPTOGRAPHIC_LENGTH))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_CRYPTOGRAPHIC_PARAMETERS))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_CRYPTOGRAPHIC_DOMAIN_PARAMETERS))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_CERTIFICATE_TYPE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_CERTIFICATE_LENGTH))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_X509_CERTIFICATE_IDENTIFIER))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_X509_CERTIFICATE_SUBJECT))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_X509_CERTIFICATE_ISSUER))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_CERTIFICATE_IDENTIFIER))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_CERTIFICATE_SUBJECT))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_CERTIFICATE_ISSUER))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_DIGITAL_SIGNATURE_ALGORITHM))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_DIGEST))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_OPERATION_POLICY_NAME))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_CRYPTOGRAPHIC_USAGE_MASK))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_LEASE_TIME))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_USAGE_LIMITS))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_STATE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_INITIAL_DATE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_ACTIVATION_DATE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_PROCESS_START_DATE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_PROTECT_STOP_DATE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_DEACTIVATION_DATE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_DESTROY_DATE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_COMPROMISE_OCCURRENCE_DATE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_COMPROMISE_DATE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_REVOCATION_REASON))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_ARCHIVE_DATE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_OBJECT_GROUP))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_FRESH))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_LINK))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_APPLICATION_SPECIFIC_INFORMATION))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_CONTACT_INFORMATION))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_LAST_CHANGE_DATE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_ALTERNATIVE_NAME))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_KEY_VALUE_PRESENT))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_KEY_VALUE_LOCATION))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_ORIGINAL_CREATION_DATE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_RANDOM_NUMBER_GENERATOR))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_PKCS_12_FRIENDLY_NAME))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_DESCRIPTION))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_COMMENT))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_SENSITIVE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_ALWAYS_SENSITIVE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_EXTRACTABLE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_NEVER_EXTRACTABLE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_is_attribute_tag(KMIP_TAG_KEY_FORMAT_TYPE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_is_attribute_tag(KMIP_TAG_REQUEST_MESSAGE))
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    TEST_PASSED(tracker, __func__);
}

int
test_get_enum_string_index(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    if(kmip_get_enum_string_index(KMIP_TAG_UNIQUE_IDENTIFIER) != 0)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_NAME) != 1)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_OBJECT_TYPE) != 2)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM) != 3)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_CRYPTOGRAPHIC_LENGTH) != 4)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_CRYPTOGRAPHIC_PARAMETERS) != 5)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_CRYPTOGRAPHIC_DOMAIN_PARAMETERS) != 6)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_CERTIFICATE_TYPE) != 7)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_CERTIFICATE_LENGTH) != 8)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_X509_CERTIFICATE_IDENTIFIER) != 9)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_X509_CERTIFICATE_SUBJECT) != 10)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_X509_CERTIFICATE_ISSUER) != 11)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_CERTIFICATE_IDENTIFIER) != 12)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_CERTIFICATE_SUBJECT) != 13)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_CERTIFICATE_ISSUER) != 14)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_DIGITAL_SIGNATURE_ALGORITHM) != 15)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_DIGEST) != 16)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_OPERATION_POLICY_NAME) != 17)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_CRYPTOGRAPHIC_USAGE_MASK) != 18)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_LEASE_TIME) != 19)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_USAGE_LIMITS) != 20)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_STATE) != 21)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_INITIAL_DATE) != 22)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_ACTIVATION_DATE) != 23)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_PROCESS_START_DATE) != 24)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_PROTECT_STOP_DATE) != 25)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_DEACTIVATION_DATE) != 26)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_DESTROY_DATE) != 27)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_COMPROMISE_OCCURRENCE_DATE) != 28)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_COMPROMISE_DATE) != 29)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_REVOCATION_REASON) != 30)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_ARCHIVE_DATE) != 31)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_OBJECT_GROUP) != 32)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_FRESH) != 33)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_LINK) != 34)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_APPLICATION_SPECIFIC_INFORMATION) != 35)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_CONTACT_INFORMATION) != 36)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_LAST_CHANGE_DATE) != 37)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_ALTERNATIVE_NAME) != 38)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_KEY_VALUE_PRESENT) != 39)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_KEY_VALUE_LOCATION) != 40)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_ORIGINAL_CREATION_DATE) != 41)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_RANDOM_NUMBER_GENERATOR) != 42)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_PKCS_12_FRIENDLY_NAME) != 43)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_DESCRIPTION) != 44)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_COMMENT) != 45)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_SENSITIVE) != 46)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_ALWAYS_SENSITIVE) != 47)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_EXTRACTABLE) != 48)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_NEVER_EXTRACTABLE) != 49)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(KMIP_TAG_KEY_FORMAT_TYPE) != 50)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_get_enum_string_index(-1) != 51)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    TEST_PASSED(tracker, __func__);
}

int
test_check_enum_value_protection_storage_masks(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    enum kmip_version v = KMIP_2_0;
    enum tag t = KMIP_TAG_PROTECTION_STORAGE_MASK;

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_SOFTWARE) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_HARDWARE) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_ON_PROCESSOR) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_ON_SYSTEM) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_OFF_SYSTEM) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_HYPERVISOR) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_OPERATING_SYSTEM) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_CONTAINER) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_ON_PREMISES) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_OFF_PREMISES) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_SELF_MANAGED) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_OUTSOURCED) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_VALIDATED) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_SAME_JURISDICTION) != KMIP_OK)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    v = KMIP_1_4;

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_SOFTWARE) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_HARDWARE) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_ON_PROCESSOR) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_ON_SYSTEM) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_OFF_SYSTEM) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_HYPERVISOR) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_OPERATING_SYSTEM) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_CONTAINER) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_ON_PREMISES) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_OFF_PREMISES) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_SELF_MANAGED) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_OUTSOURCED) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_VALIDATED) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, KMIP_PROTECT_SAME_JURISDICTION) != KMIP_INVALID_FOR_VERSION)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    if(kmip_check_enum_value(v, t, -1) != KMIP_ENUM_MISMATCH)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    TEST_PASSED(tracker, __func__);
}

int
test_init_protocol_version(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    kmip_init_protocol_version(NULL, KMIP_1_0);

    ProtocolVersion pv = {0};

    if(pv.major != 0)
        TEST_FAILED(tracker, __func__, __LINE__);
    if(pv.minor != 0)
        TEST_FAILED(tracker, __func__, __LINE__);

    kmip_init_protocol_version(&pv, KMIP_1_0);

    if(pv.major != 1)
        TEST_FAILED(tracker, __func__, __LINE__);
    if(pv.minor != 0)
        TEST_FAILED(tracker, __func__, __LINE__);

    kmip_init_protocol_version(&pv, KMIP_1_1);

    if(pv.major != 1)
        TEST_FAILED(tracker, __func__, __LINE__);
    if(pv.minor != 1)
        TEST_FAILED(tracker, __func__, __LINE__);

    kmip_init_protocol_version(&pv, KMIP_1_2);

    if(pv.major != 1)
        TEST_FAILED(tracker, __func__, __LINE__);
    if(pv.minor != 2)
        TEST_FAILED(tracker, __func__, __LINE__);

    kmip_init_protocol_version(&pv, KMIP_1_3);

    if(pv.major != 1)
        TEST_FAILED(tracker, __func__, __LINE__);
    if(pv.minor != 3)
        TEST_FAILED(tracker, __func__, __LINE__);

    kmip_init_protocol_version(&pv, KMIP_1_4);

    if(pv.major != 1)
        TEST_FAILED(tracker, __func__, __LINE__);
    if(pv.minor != 4)
        TEST_FAILED(tracker, __func__, __LINE__);

    kmip_init_protocol_version(&pv, KMIP_2_0);

    if(pv.major != 2)
        TEST_FAILED(tracker, __func__, __LINE__);
    if(pv.minor != 0)
        TEST_FAILED(tracker, __func__, __LINE__);

    TEST_PASSED(tracker, __func__);
}

int
test_init_request_batch_item(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    kmip_init_request_batch_item(NULL);

    RequestBatchItem rbi = {0};

    if(rbi.operation != 0)
        TEST_FAILED(tracker, __func__, __LINE__);
    if(rbi.unique_batch_item_id != NULL)
        TEST_FAILED(tracker, __func__, __LINE__);
    if(rbi.request_payload != NULL)
        TEST_FAILED(tracker, __func__, __LINE__);
    if(rbi.ephemeral != 0)
        TEST_FAILED(tracker, __func__, __LINE__);

    kmip_init_request_batch_item(&rbi);

    if(rbi.operation != 0)
        TEST_FAILED(tracker, __func__, __LINE__);
    if(rbi.unique_batch_item_id != NULL)
        TEST_FAILED(tracker, __func__, __LINE__);
    if(rbi.request_payload != NULL)
        TEST_FAILED(tracker, __func__, __LINE__);
    if(rbi.ephemeral != KMIP_UNSET)
        TEST_FAILED(tracker, __func__, __LINE__);

    TEST_PASSED(tracker, __func__);
}

int
test_print_attributes(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* For now this will probably be left as a placeholder for a
       future test. Ideally the print functions would output to
       an arbitrary buffer so that we can verify that they are
       correctly displaying structure content and formatting.
       Since they currently use printf directly, this may be hard
       to do in the short term.
    */
    TEST_FAILED(tracker, __func__, __LINE__);
}

int
test_free_attributes(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* Build a dynamically allocated Attributes structure. Free it
       with this function. Verify that all internal pointers and
       fields are correctly nullified.

       Ideally, hook into the free function managed by the context
       and use that hook to verify that the correct free calls are
       made on the internal Attributes structure pointers. This
       may require more infrastructure work than currently exists.
    */
    TEST_FAILED(tracker, __func__, __LINE__);
}

int
test_compare_attributes(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* Build two separate identical Attributes structures. Compare
       them with this function and confirm they match.

       Build two separate different Attributes structures. Compare
       them with this function and confirm they do not match. This
       may require multiple rounds, changing different parts of the
       underlying Attributes structure. It may make more sense to
       split this into multiple test functions.
    */
    TEST_FAILED(tracker, __func__, __LINE__);
}

int
test_deep_copy_int32(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    int32 expected = 42;
    int32 *observed = NULL;

    observed = kmip_deep_copy_int32(NULL, NULL);
    if(observed != NULL)
        TEST_FAILED(tracker, __func__, __LINE__);

    KMIP ctx = {0};
    kmip_init(&ctx, NULL, 0, KMIP_1_0);

    observed = kmip_deep_copy_int32(&ctx, NULL);
    if(observed != NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    observed = kmip_deep_copy_int32(&ctx, &expected);
    if(observed == NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(*observed != expected)
    {
        kmip_print_integer(expected);
        kmip_print_integer(*observed);
        ctx.free_func(ctx.state, observed);
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    ctx.free_func(ctx.state, observed);
    kmip_destroy(&ctx);

    TEST_PASSED(tracker, __func__);
}

int
test_deep_copy_text_string(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    TextString expected = {0};
    expected.value = "example";
    expected.size = 7;
    TextString *observed = NULL;

    observed = kmip_deep_copy_text_string(NULL, NULL);
    if(observed != NULL)
        TEST_FAILED(tracker, __func__, __LINE__);

    KMIP ctx = {0};
    kmip_init(&ctx, NULL, 0, KMIP_1_0);

    observed = kmip_deep_copy_text_string(&ctx, NULL);
    if(observed != NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    observed = kmip_deep_copy_text_string(&ctx, &expected);
    if(observed == NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_compare_text_string(&expected, observed))
    {
        kmip_print_text_string(1, "Name Value", &expected);
        kmip_print_text_string(1, "Name Value", observed);
        kmip_free_text_string(&ctx, observed);
        ctx.free_func(ctx.state, observed);
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_free_text_string(&ctx, observed);
    ctx.free_func(ctx.state, observed);
    kmip_destroy(&ctx);

    TEST_PASSED(tracker, __func__);
}

int
test_deep_copy_name(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    TextString value = {0};
    value.value = "example";
    value.size = 7;
    Name expected = {0};
    expected.value = &value;
    expected.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING;
    Name *observed = NULL;

    observed = kmip_deep_copy_name(NULL, NULL);
    if(observed != NULL)
        TEST_FAILED(tracker, __func__, __LINE__);

    KMIP ctx = {0};
    kmip_init(&ctx, NULL, 0, KMIP_1_0);

    observed = kmip_deep_copy_name(&ctx, NULL);
    if(observed != NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    observed = kmip_deep_copy_name(&ctx, &expected);
    if(observed == NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_compare_name(&expected, observed))
    {
        kmip_print_name(1, &expected);
        kmip_print_name(1, observed);
        kmip_free_name(&ctx, observed);
        ctx.free_func(ctx.state, observed);
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_free_name(&ctx, observed);
    ctx.free_func(ctx.state, observed);
    kmip_destroy(&ctx);

    TEST_PASSED(tracker, __func__);
}

int
test_deep_copy_attribute(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    Attribute expected = {0};
    kmip_init_attribute(&expected);
    Attribute *observed = NULL;

    observed = kmip_deep_copy_attribute(NULL, NULL);
    if(observed != NULL)
        TEST_FAILED(tracker, __func__, __LINE__);

    KMIP ctx = {0};
    kmip_init(&ctx, NULL, 0, KMIP_1_0);

    observed = kmip_deep_copy_attribute(&ctx, NULL);
    if(observed != NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    /* Test deep copying an "empty" attribute. */
    observed = kmip_deep_copy_attribute(&ctx, &expected);
    if(observed == NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_compare_attribute(&expected, observed))
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, observed);
        kmip_free_attribute(&ctx, observed);
        ctx.free_func(ctx.state, observed);
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_free_attribute(&ctx, observed);
    ctx.free_func(ctx.state, observed);

    /* Test deep copying a Unique Identifier attribute. */
    TextString uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    expected.type = KMIP_ATTR_UNIQUE_IDENTIFIER;
    expected.value = &uuid;

    observed = kmip_deep_copy_attribute(&ctx, &expected);
    if(observed == NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_compare_attribute(&expected, observed))
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, observed);
        kmip_free_attribute(&ctx, observed);
        ctx.free_func(ctx.state, observed);
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_free_attribute(&ctx, observed);
    ctx.free_func(ctx.state, observed);

    /* Test deep copying an Operation Policy Name attribute. */
    TextString policy = {0};
    policy.value = "default";
    policy.size = 7;
    expected.type = KMIP_ATTR_OPERATION_POLICY_NAME;
    expected.value = &policy;

    observed = kmip_deep_copy_attribute(&ctx, &expected);
    if(observed == NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_compare_attribute(&expected, observed))
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, observed);
        kmip_free_attribute(&ctx, observed);
        ctx.free_func(ctx.state, observed);
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_free_attribute(&ctx, observed);
    ctx.free_func(ctx.state, observed);

    /* Test deep copying a Name attribute. */
    TextString name_value = {0};
    name_value.value = "example";
    name_value.size = 7;
    Name name = {0};
    name.value = &name_value;
    name.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING;
    expected.type = KMIP_ATTR_NAME;
    expected.value = &name;

    observed = kmip_deep_copy_attribute(&ctx, &expected);
    if(observed == NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_compare_attribute(&expected, observed))
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, observed);
        kmip_free_attribute(&ctx, observed);
        ctx.free_func(ctx.state, observed);
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_free_attribute(&ctx, observed);
    ctx.free_func(ctx.state, observed);

    /* Test deep copying an Object Type attribute. */
    enum object_type object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    expected.type = KMIP_ATTR_OBJECT_TYPE;
    expected.value = &object_type;

    observed = kmip_deep_copy_attribute(&ctx, &expected);
    if(observed == NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_compare_attribute(&expected, observed))
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, observed);
        kmip_free_attribute(&ctx, observed);
        ctx.free_func(ctx.state, observed);
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_free_attribute(&ctx, observed);
    ctx.free_func(ctx.state, observed);

    /* Test deep copying a Cryptographic Algorithm attribute. */
    enum cryptographic_algorithm cryptographic_algorithm = KMIP_CRYPTOALG_AES;
    expected.type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    expected.value = &cryptographic_algorithm;

    observed = kmip_deep_copy_attribute(&ctx, &expected);
    if(observed == NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_compare_attribute(&expected, observed))
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, observed);
        kmip_free_attribute(&ctx, observed);
        ctx.free_func(ctx.state, observed);
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_free_attribute(&ctx, observed);
    ctx.free_func(ctx.state, observed);

    /* Test deep copying a Cryptographic Length attribute. */
    int32 cryptographic_length = 256;
    expected.type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    expected.value = &cryptographic_length;

    observed = kmip_deep_copy_attribute(&ctx, &expected);
    if(observed == NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_compare_attribute(&expected, observed))
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, observed);
        kmip_free_attribute(&ctx, observed);
        ctx.free_func(ctx.state, observed);
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_free_attribute(&ctx, observed);
    ctx.free_func(ctx.state, observed);

    /* Test deep copying a Cryptographic Usage Mask attribute. */
    int32 cryptographic_usage_mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT;
    expected.type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK;
    expected.value = &cryptographic_usage_mask;

    observed = kmip_deep_copy_attribute(&ctx, &expected);
    if(observed == NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_compare_attribute(&expected, observed))
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, observed);
        kmip_free_attribute(&ctx, observed);
        ctx.free_func(ctx.state, observed);
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_free_attribute(&ctx, observed);
    ctx.free_func(ctx.state, observed);

    /* Test deep copying a State attribute. */
    enum state state = KMIP_STATE_ACTIVE;
    expected.type = KMIP_ATTR_STATE;
    expected.value = &state;

    observed = kmip_deep_copy_attribute(&ctx, &expected);
    if(observed == NULL)
    {
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }
    if(!kmip_compare_attribute(&expected, observed))
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, observed);
        kmip_free_attribute(&ctx, observed);
        ctx.free_func(ctx.state, observed);
        kmip_destroy(&ctx);
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_free_attribute(&ctx, observed);
    ctx.free_func(ctx.state, observed);
    kmip_destroy(&ctx);

    TEST_PASSED(tracker, __func__);
}

int
test_decode_int8_be(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[1] = {0x42};
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    int8 value = 0;
    
    int result = kmip_decode_int8_be(&ctx, &value);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        value == 0x42, 
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_int32_be(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[4] = {0x11, 0x22, 0x33, 0x44};
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);

    int32 expected = 0x11223344;
    int32 observed = 0;
    
    int result = kmip_decode_int32_be(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        observed == expected,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_int64_be(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[8] = {
        0x01, 0xB6, 0x9B, 0x4B, 0xA5, 0x74, 0x92, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    int64 expected = 0x01B69B4BA5749200;
    int64 observed = 0;
    
    int result = kmip_decode_int64_be(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        observed == expected,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_integer(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[16] = {
        0x42, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[16] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    int result = kmip_encode_integer(&ctx, KMIP_TAG_DEFAULT, 8);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_integer(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[16] = {
        0x42, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00
    };

    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    int32 expected = 8;
    int32 observed = 0;
    
    int result = kmip_decode_integer(&ctx, KMIP_TAG_DEFAULT, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        observed == expected,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_long(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[16] = {
        0x42, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08,
        0x01, 0xB6, 0x9B, 0x4B, 0xA5, 0x74, 0x92, 0x00
    };
    
    uint8 observed[16] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    int result = kmip_encode_long(&ctx, KMIP_TAG_DEFAULT, 123456789000000000);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_long(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[16] = {
        0x42, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08,
        0x01, 0xB6, 0x9B, 0x4B, 0xA5, 0x74, 0x92, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    int64 expected = 0x01B69B4BA5749200;
    int64 observed = 0;
    
    int result = kmip_decode_long(&ctx, KMIP_TAG_DEFAULT, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        observed == expected,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_enum(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[16] = {
        0x42, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[16] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    int result = kmip_encode_enum(&ctx, KMIP_TAG_DEFAULT, KMIP_CRYPTOALG_AES);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_enum(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[16] = {
        0x42, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    enum cryptographic_algorithm expected = KMIP_CRYPTOALG_AES;
    enum cryptographic_algorithm observed = 0;
    
    int result = kmip_decode_enum(&ctx, KMIP_TAG_DEFAULT, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        observed == expected,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_bool(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[16] = {
        0x42, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
    };
    
    uint8 observed[16] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    int result = kmip_encode_bool(&ctx, KMIP_TAG_DEFAULT, KMIP_TRUE);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_bool(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[16] = {
        0x42, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    bool32 expected = KMIP_TRUE;
    bool32 observed = 0;
    
    int result = kmip_decode_bool(&ctx, KMIP_TAG_DEFAULT, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        observed == expected,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_text_string(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[24] = {
        0x42, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0B,
        0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F,
        0x72, 0x6C, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[24] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);

    struct text_string example = {0};
    example.value = "Hello World";
    example.size = 11;
    
    int result = kmip_encode_text_string(&ctx, KMIP_TAG_DEFAULT, &example);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_text_string(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[24] = {
        0x42, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0B,
        0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F,
        0x72, 0x6C, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);

    struct text_string expected = {0};
    expected.value = "Hello World";
    expected.size = 11;
    struct text_string observed = {0};
    
    int result = kmip_decode_text_string(&ctx, KMIP_TAG_DEFAULT, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_text_string(&expected, &observed),
        result,
        __func__);
    kmip_free_text_string(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_byte_string(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[16] = {
        0x42, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03,
        0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[16] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    uint8 str[3] = {0x01, 0x02, 0x03};
    
    struct byte_string example = {0};
    example.value = str;
    example.size = 3;
    
    int result = kmip_encode_byte_string(&ctx, KMIP_TAG_DEFAULT, &example);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_byte_string(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[16] = {
        0x42, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03,
        0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);

    uint8 str[3] = {0x01, 0x02, 0x03};
    
    struct byte_string expected = {0};
    expected.value = str;
    expected.size = 3;
    struct byte_string observed = {0};
    
    int result = kmip_decode_byte_string(&ctx, KMIP_TAG_DEFAULT, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_byte_string(&expected, &observed),
        result,
        __func__);
    kmip_free_byte_string(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_date_time(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[16] = {
        0x42, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x47, 0xDA, 0x67, 0xF8
    };
    
    uint8 observed[16] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    int result = kmip_encode_date_time(&ctx, KMIP_TAG_DEFAULT, 1205495800);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_date_time(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[16] = {
        0x42, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x47, 0xDA, 0x67, 0xF8
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint64 expected = 1205495800;
    uint64 observed = 0;
    
    int result = kmip_decode_date_time(&ctx, KMIP_TAG_DEFAULT, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        observed == expected,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_interval(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[16] = {
        0x42, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x0D, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[16] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    int result = kmip_encode_interval(&ctx, KMIP_TAG_DEFAULT, 864000);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_interval(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[16] = {
        0x42, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x0D, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint32 expected = 864000;
    uint32 observed = 0;
    
    int result = kmip_decode_interval(&ctx, KMIP_TAG_DEFAULT, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        observed == expected,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_name(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[48] = {
        0x42, 0x00, 0x53, 0x01, 0x00, 0x00, 0x00, 0x28,
        0x42, 0x00, 0x55, 0x07, 0x00, 0x00, 0x00, 0x09,
        0x54, 0x65, 0x6D, 0x70, 0x6C, 0x61, 0x74, 0x65,
        0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[48] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string value = {0};
    value.value = "Template1";
    value.size = 9;
    
    struct name n = {0};
    n.value = &value;
    n.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING;
    
    int result = kmip_encode_name(&ctx, &n);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_name(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[48] = {
        0x42, 0x00, 0x53, 0x01, 0x00, 0x00, 0x00, 0x28,
        0x42, 0x00, 0x55, 0x07, 0x00, 0x00, 0x00, 0x09,
        0x54, 0x65, 0x6D, 0x70, 0x6C, 0x61, 0x74, 0x65,
        0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string value = {0};
    value.value = "Template1";
    value.size = 9;
    
    struct name expected = {0};
    expected.value = &value;
    expected.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING;
    struct name observed = {0};
    
    int result = kmip_decode_name(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_name(&expected, &observed),
        result,
        __func__);
    kmip_free_name(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_protection_storage_masks(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following set of values:
    *  Protection Storage Masks
    *      Protection Storage Mask
    *          Software
    *          Hardware
    *          On Processor
    *          On System
    *          Off System
    *          Hypervisor
    *          Operating System
    *          Container
    *          On Premises
    *          Off Premises
    *          Self Managed
    *          Outsourced
    *          Validated
    *          Same Jurisdiction
    *      Protection Storage Mask
    *          Software
    *          Hardware
    */
    uint8 expected[40] = {
        0x42, 0x01, 0x5F, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x01, 0x5E, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x5E, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00
    };

    uint8 observed[40] = {0};
    KMIP ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_2_0);

    LinkedList list = {0};
    LinkedListItem item_1 = {0};
    int32 mask_1 = 0x3FFF;
    item_1.data = &mask_1;

    LinkedListItem item_2 = {0};
    int32 mask_2 = 0x0003;
    item_2.data = &mask_2;

    kmip_linked_list_enqueue(&list, &item_1);
    kmip_linked_list_enqueue(&list, &item_2);

    ProtectionStorageMasks psm = {0};
    psm.masks = &list;

    int result = kmip_encode_protection_storage_masks(&ctx, &psm);
    result = report_encoding_test_result(tracker, &ctx, expected, observed, result, __func__);

    kmip_destroy(&ctx);

    return(result);
}

int
test_decode_protection_storage_masks(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following set of values:
    *  Protection Storage Masks
    *      Protection Storage Mask
    *          Software
    *          Hardware
    *          On Processor
    *          On System
    *          Off System
    *          Hypervisor
    *          Operating System
    *          Container
    *          On Premises
    *          Off Premises
    *          Self Managed
    *          Outsourced
    *          Validated
    *          Same Jurisdiction
    *      Protection Storage Mask
    *          Software
    *          Hardware
    */
    uint8 encoding[40] = {
        0x42, 0x01, 0x5F, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x01, 0x5E, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x5E, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00
    };

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);

    LinkedList list = {0};
    LinkedListItem item_1 = {0};
    int32 mask_1 = 0x3FFF;
    item_1.data = &mask_1;

    LinkedListItem item_2 = {0};
    int32 mask_2 = 0x0003;
    item_2.data = &mask_2;

    kmip_linked_list_enqueue(&list, &item_1);
    kmip_linked_list_enqueue(&list, &item_2);

    ProtectionStorageMasks expected = {0};
    expected.masks = &list;

    ProtectionStorageMasks observed = {0};
    int result = kmip_decode_protection_storage_masks(&ctx, &observed);
    int comparison = kmip_compare_protection_storage_masks(&expected, &observed);
    if(!comparison)
    {
        kmip_print_protection_storage_masks(1, &expected);
        kmip_print_protection_storage_masks(1, &observed);
    }
    result = report_decoding_test_result(tracker, &ctx, comparison, result, __func__);

    kmip_free_protection_storage_masks(&ctx, &observed);
    kmip_destroy(&ctx);

    return(result);
}

int
test_encode_attribute_unique_identifier(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[88] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x50,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x11,
        0x55, 0x6E, 0x69, 0x71, 0x75, 0x65, 0x20, 0x49,
        0x64, 0x65, 0x6E, 0x74, 0x69, 0x66, 0x69, 0x65,
        0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0B, 0x07, 0x00, 0x00, 0x00, 0x24,
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38,
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66,
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D,
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63,
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[88] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    struct attribute attr = {0};
    kmip_init_attribute(&attr);
    
    attr.type = KMIP_ATTR_UNIQUE_IDENTIFIER;
    attr.value = &uuid;
    
    int result = kmip_encode_attribute(&ctx, &attr);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_attribute_unique_identifier(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[88] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x50,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x11,
        0x55, 0x6E, 0x69, 0x71, 0x75, 0x65, 0x20, 0x49,
        0x64, 0x65, 0x6E, 0x74, 0x69, 0x66, 0x69, 0x65,
        0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0B, 0x07, 0x00, 0x00, 0x00, 0x24,
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38,
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66,
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D,
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63,
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    struct attribute expected = {0};
    kmip_init_attribute(&expected);
    expected.type = KMIP_ATTR_UNIQUE_IDENTIFIER;
    expected.value = &uuid;
    struct attribute observed = {0};
    kmip_init_attribute(&observed);
    
    int result = kmip_decode_attribute(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_attribute(&expected, &observed),
        result,
        __func__);
    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_attribute_name(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[72] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x40,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x04,
        0x4E, 0x61, 0x6D, 0x65, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x00, 0x28,
        0x42, 0x00, 0x55, 0x07, 0x00, 0x00, 0x00, 0x09,
        0x54, 0x65, 0x6D, 0x70, 0x6C, 0x61, 0x74, 0x65,
        0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[72] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string value = {0};
    value.value = "Template1";
    value.size = 9;
    
    struct name n = {0};
    n.value = &value;
    n.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING;
    
    struct attribute attr = {0};
    kmip_init_attribute(&attr);
    
    attr.type = KMIP_ATTR_NAME;
    attr.value = &n;
    
    int result = kmip_encode_attribute(&ctx, &attr);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_attribute_name(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[72] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x40,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x04,
        0x4E, 0x61, 0x6D, 0x65, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x00, 0x28,
        0x42, 0x00, 0x55, 0x07, 0x00, 0x00, 0x00, 0x09,
        0x54, 0x65, 0x6D, 0x70, 0x6C, 0x61, 0x74, 0x65,
        0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string value = {0};
    value.value = "Template1";
    value.size = 9;
    
    struct name n = {0};
    n.value = &value;
    n.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING;
    
    struct attribute expected = {0};
    kmip_init_attribute(&expected);
    expected.type = KMIP_ATTR_NAME;
    expected.value = &n;
    struct attribute observed = {0};
    kmip_init_attribute(&observed);
    
    int result = kmip_decode_attribute(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_attribute(&expected, &observed),
        result,
        __func__);
    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_attribute_object_type(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[48] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x28,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x0B,
        0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x54,
        0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[48] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    enum object_type t = KMIP_OBJTYPE_SYMMETRIC_KEY;
    struct attribute attr = {0};
    kmip_init_attribute(&attr);
    
    attr.type = KMIP_ATTR_OBJECT_TYPE;
    attr.value = &t;
    
    int result = kmip_encode_attribute(&ctx, &attr);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_attribute_object_type(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[48] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x28,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x0B,
        0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x54,
        0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    enum object_type t = KMIP_OBJTYPE_SYMMETRIC_KEY;
    struct attribute expected = {0};
    kmip_init_attribute(&expected);
    expected.type = KMIP_ATTR_OBJECT_TYPE;
    expected.value = &t;
    struct attribute observed = {0};
    kmip_init_attribute(&observed);
    
    int result = kmip_decode_attribute(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_attribute(&expected, &observed),
        result,
        __func__);
    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_attribute_cryptographic_algorithm(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[56] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x17,
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72,
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x6C,
        0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00,
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[56] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    enum cryptographic_algorithm a = KMIP_CRYPTOALG_AES;
    struct attribute attr = {0};
    kmip_init_attribute(&attr);
    
    attr.type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    attr.value = &a;
    
    int result = kmip_encode_attribute(&ctx, &attr);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_attribute_cryptographic_algorithm(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[56] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x17,
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72,
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x6C,
        0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00,
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    enum cryptographic_algorithm a = KMIP_CRYPTOALG_AES;
    struct attribute expected = {0};
    kmip_init_attribute(&expected);
    expected.type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    expected.value = &a;
    struct attribute observed = {0};
    kmip_init_attribute(&observed);
    
    int result = kmip_decode_attribute(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_attribute(&expected, &observed),
        result,
        __func__);
    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_attribute_cryptographic_length(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[56] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x14,
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72,
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x4C, 0x65,
        0x6E, 0x67, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[56] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    int32 length = 128;
    struct attribute attr = {0};
    kmip_init_attribute(&attr);
    
    attr.type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    attr.value = &length;
    
    int result = kmip_encode_attribute(&ctx, &attr);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_attribute_cryptographic_length(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[56] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x14,
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72,
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x4C, 0x65,
        0x6E, 0x67, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    int32 length = 128;
    struct attribute expected = {0};
    kmip_init_attribute(&expected);
    expected.type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    expected.value = &length;
    struct attribute observed = {0};
    kmip_init_attribute(&observed);
    
    int result = kmip_decode_attribute(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_attribute(&expected, &observed),
        result,
        __func__);
    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_attribute_operation_policy_name(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[56] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x15,
        0x4F, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
        0x6E, 0x20, 0x50, 0x6F, 0x6C, 0x69, 0x63, 0x79,
        0x20, 0x4E, 0x61, 0x6D, 0x65, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0B, 0x07, 0x00, 0x00, 0x00, 0x07,
        0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x00
    };
    
    uint8 observed[56] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string policy = {0};
    policy.value = "default";
    policy.size = 7;
    
    struct attribute attr = {0};
    kmip_init_attribute(&attr);
    
    attr.type = KMIP_ATTR_OPERATION_POLICY_NAME;
    attr.value = &policy;
    
    int result = kmip_encode_attribute(&ctx, &attr);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_attribute_operation_policy_name(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[56] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x15,
        0x4F, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
        0x6E, 0x20, 0x50, 0x6F, 0x6C, 0x69, 0x63, 0x79,
        0x20, 0x4E, 0x61, 0x6D, 0x65, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0B, 0x07, 0x00, 0x00, 0x00, 0x07,
        0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string policy = {0};
    policy.value = "default";
    policy.size = 7;
    
    struct attribute expected = {0};
    kmip_init_attribute(&expected);
    expected.type = KMIP_ATTR_OPERATION_POLICY_NAME;
    expected.value = &policy;
    struct attribute observed = {0};
    kmip_init_attribute(&observed);
    
    int result = kmip_decode_attribute(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_attribute(&expected, &observed),
        result,
        __func__);
    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_attribute_cryptographic_usage_mask(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[56] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18,
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72,
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x55, 0x73,
        0x61, 0x67, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x6B,
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[56] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT;
    struct attribute attr = {0};
    kmip_init_attribute(&attr);
    
    attr.type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK;
    attr.value = &mask;
    
    int result = kmip_encode_attribute(&ctx, &attr);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_attribute_cryptographic_usage_mask(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[56] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18,
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72,
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x55, 0x73,
        0x61, 0x67, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x6B,
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT;
    struct attribute expected = {0};
    kmip_init_attribute(&expected);
    expected.type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK;
    expected.value = &mask;
    struct attribute observed = {0};
    kmip_init_attribute(&observed);
    
    int result = kmip_decode_attribute(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_attribute(&expected, &observed),
        result,
        __func__);
    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_attribute_state(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[40] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x05, 
        0x53, 0x74, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[40] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    enum state s = KMIP_STATE_PRE_ACTIVE;
    struct attribute attr = {0};
    kmip_init_attribute(&attr);
    
    attr.type = KMIP_ATTR_STATE;
    attr.value = &s;
    
    int result = kmip_encode_attribute(&ctx, &attr);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_attribute_state(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[40] = {
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x05, 
        0x53, 0x74, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    enum state s = KMIP_STATE_PRE_ACTIVE;
    struct attribute expected = {0};
    kmip_init_attribute(&expected);
    expected.type = KMIP_ATTR_STATE;
    expected.value = &s;
    struct attribute observed = {0};
    kmip_init_attribute(&observed);
    
    int result = kmip_decode_attribute(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_attribute(&expected, &observed),
        result,
        __func__);
    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_protocol_version(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[40] = {
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[40] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    int result = kmip_encode_protocol_version(&ctx, &pv);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_protocol_version(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[40] = {
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct protocol_version expected = {0};
    expected.major = 1;
    expected.minor = 0;
    struct protocol_version observed = {0};
    
    int result = kmip_decode_protocol_version(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_protocol_version(&expected, &observed),
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_cryptographic_parameters(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[72] = {
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x40,
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x5F, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x38, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x83, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[72] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct cryptographic_parameters cp = {0};
    cp.block_cipher_mode = KMIP_BLOCK_CBC;
    cp.padding_method = KMIP_PAD_PKCS5;
    cp.hashing_algorithm = KMIP_HASH_SHA1;
    cp.key_role_type = KMIP_ROLE_KEK;
    
    int result = kmip_encode_cryptographic_parameters(&ctx, &cp);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_cryptographic_parameters(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[72] = {
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x40,
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x5F, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x38, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x83, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct cryptographic_parameters expected = {0};
    kmip_init_cryptographic_parameters(&expected);
    expected.block_cipher_mode = KMIP_BLOCK_CBC;
    expected.padding_method = KMIP_PAD_PKCS5;
    expected.hashing_algorithm = KMIP_HASH_SHA1;
    expected.key_role_type = KMIP_ROLE_KEK;
    struct cryptographic_parameters observed = {0};
    kmip_init_cryptographic_parameters(&observed);
    
    int result = kmip_decode_cryptographic_parameters(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_cryptographic_parameters(&expected, &observed),
        result,
        __func__);
    kmip_free_cryptographic_parameters(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_encryption_key_information(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[80] = {
        0x42, 0x00, 0x36, 0x01, 0x00, 0x00, 0x00, 0x48,
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24,
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35,
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D,
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10, 
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[80] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "100182d5-72b8-47aa-8383-4d97d512e98a";
    uuid.size = 36;
    
    struct cryptographic_parameters cp = {0};
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;
    
    struct encryption_key_information eki = {0};
    eki.unique_identifier = &uuid;
    eki.cryptographic_parameters = &cp;
    
    int result = kmip_encode_encryption_key_information(&ctx, &eki);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_encryption_key_information(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[80] = {
        0x42, 0x00, 0x36, 0x01, 0x00, 0x00, 0x00, 0x48,
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24,
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35,
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D,
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10, 
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "100182d5-72b8-47aa-8383-4d97d512e98a";
    uuid.size = 36;
    
    struct cryptographic_parameters cp = {0};
    kmip_init_cryptographic_parameters(&cp);
    
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;
    
    struct encryption_key_information expected = {0};
    expected.unique_identifier = &uuid;
    expected.cryptographic_parameters = &cp;
    
    struct encryption_key_information observed = {0};
    
    int result = kmip_decode_encryption_key_information(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_encryption_key_information(&expected, &observed),
        result,
        __func__);
    kmip_free_encryption_key_information(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_mac_signature_key_information(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[80] = {
        0x42, 0x00, 0x4E, 0x01, 0x00, 0x00, 0x00, 0x48,
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24,
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35,
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D,
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10, 
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[80] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "100182d5-72b8-47aa-8383-4d97d512e98a";
    uuid.size = 36;

    struct cryptographic_parameters cp = {0};
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;

    struct mac_signature_key_information mski = {0};
    mski.unique_identifier = &uuid;
    mski.cryptographic_parameters = &cp;
    
    int result = kmip_encode_mac_signature_key_information(&ctx, &mski);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_mac_signature_key_information(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[80] = {
        0x42, 0x00, 0x4E, 0x01, 0x00, 0x00, 0x00, 0x48,
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24,
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35,
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D,
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10, 
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "100182d5-72b8-47aa-8383-4d97d512e98a";
    uuid.size = 36;

    struct cryptographic_parameters cp = {0};
    kmip_init_cryptographic_parameters(&cp);
    
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;

    struct mac_signature_key_information expected = {0};
    expected.unique_identifier = &uuid;
    expected.cryptographic_parameters = &cp;
    
    struct mac_signature_key_information observed = {0};
    
    int result = kmip_decode_mac_signature_key_information(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_mac_signature_key_information(&expected, &observed),
        result,
        __func__);
    kmip_free_mac_signature_key_information(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_key_wrapping_data(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[104] = {
        0x42, 0x00, 0x46, 0x01, 0x00, 0x00, 0x00, 0x60, 
        0x42, 0x00, 0x9E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x36, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35,
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D, 
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10,
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[104] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "100182d5-72b8-47aa-8383-4d97d512e98a";
    uuid.size = 36;
    
    struct cryptographic_parameters cp = {0};
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;
    
    struct encryption_key_information eki = {0};
    eki.unique_identifier = &uuid;
    eki.cryptographic_parameters = &cp;
    
    struct key_wrapping_data kwd = {0};
    kwd.wrapping_method = KMIP_WRAP_ENCRYPT;
    kwd.encryption_key_info = &eki;
    
    int result = kmip_encode_key_wrapping_data(&ctx, &kwd);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_key_wrapping_data(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[104] = {
        0x42, 0x00, 0x46, 0x01, 0x00, 0x00, 0x00, 0x60, 
        0x42, 0x00, 0x9E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x36, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35,
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D, 
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10,
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "100182d5-72b8-47aa-8383-4d97d512e98a";
    uuid.size = 36;
    
    struct cryptographic_parameters cp = {0};
    kmip_init_cryptographic_parameters(&cp);
    
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;
    
    struct encryption_key_information eki = {0};
    eki.unique_identifier = &uuid;
    eki.cryptographic_parameters = &cp;
    
    struct key_wrapping_data expected = {0};
    expected.wrapping_method = KMIP_WRAP_ENCRYPT;
    expected.encryption_key_info = &eki;
    
    struct key_wrapping_data observed = {0};
    
    int result = kmip_decode_key_wrapping_data(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_key_wrapping_data(&expected, &observed),
        result,
        __func__);
    kmip_free_key_wrapping_data(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_key_material_byte_string(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[24] = {
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x10,
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
    };
    
    uint8 observed[24] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    uint8 value[16] = {
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    int result = kmip_encode_key_material(&ctx, KMIP_KEYFORMAT_RAW, &key);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_key_material_byte_string(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[24] = {
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x10,
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 value[16] = {
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
    };
    struct byte_string expected = {0};
    expected.value = value;
    expected.size = ARRAY_LENGTH(value);
    
    struct byte_string *expected_ptr = &expected;
    struct byte_string *observed_ptr = NULL;
    
    int result = kmip_decode_key_material(
        &ctx,
        KMIP_KEYFORMAT_RAW,
        (void**)&observed_ptr);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_key_material(KMIP_KEYFORMAT_RAW, (void**)&expected_ptr, (void**)&observed_ptr),
        result,
        __func__);
    kmip_free_key_material(&ctx, KMIP_KEYFORMAT_RAW, (void**)&observed_ptr);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_key_material_transparent_symmetric_key(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[48] = {
        0x42, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x28, 
        0x42, 0x00, 0x3F, 0x08, 0x00, 0x00, 0x00, 0x20, 
        0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 
        0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77,
        0x88, 0x88, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xBB,
        0xCC, 0xCC, 0xDD, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF
    };
    
    uint8 observed[48] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    uint8 value[32] = {
        0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 
        0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77,
        0x88, 0x88, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xBB,
        0xCC, 0xCC, 0xDD, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    struct transparent_symmetric_key tsk = {0};
    tsk.key = &key;
    
    int result = kmip_encode_key_material(&ctx, KMIP_KEYFORMAT_TRANS_SYMMETRIC_KEY, &tsk);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_key_material_transparent_symmetric_key(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[48] = {
        0x42, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x28, 
        0x42, 0x00, 0x3F, 0x08, 0x00, 0x00, 0x00, 0x20, 
        0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 
        0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77,
        0x88, 0x88, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xBB,
        0xCC, 0xCC, 0xDD, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 value[32] = {
        0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 
        0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77,
        0x88, 0x88, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xBB,
        0xCC, 0xCC, 0xDD, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    struct transparent_symmetric_key expected = {0};
    expected.key = &key;
    
    struct transparent_symmetric_key *expected_ptr = &expected;
    struct transparent_symmetric_key *observed_ptr = NULL;
    
    int result = kmip_decode_key_material(
        &ctx,
        KMIP_KEYFORMAT_TRANS_SYMMETRIC_KEY,
        (void**)&observed_ptr);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_key_material(KMIP_KEYFORMAT_TRANS_SYMMETRIC_KEY, (void**)&expected_ptr, (void**)&observed_ptr),
        result,
        __func__);
    kmip_free_key_material(
        &ctx,
        KMIP_KEYFORMAT_TRANS_SYMMETRIC_KEY,
        (void**)&observed_ptr);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_key_value(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[32] = {
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x18,
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x10,
        0xD3, 0x51, 0x91, 0x0F, 0x1D, 0x79, 0x34, 0xD6,
        0xE2, 0xAE, 0x17, 0x57, 0x65, 0x64, 0xE2, 0xBC
    };
    
    uint8 observed[32] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    uint8 value[16] = {
        0xD3, 0x51, 0x91, 0x0F, 0x1D, 0x79, 0x34, 0xD6,
        0xE2, 0xAE, 0x17, 0x57, 0x65, 0x64, 0xE2, 0xBC
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &key;
    
    int result = kmip_encode_key_value(&ctx, KMIP_KEYFORMAT_RAW, &kv);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_key_value(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[32] = {
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x18,
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x10,
        0xD3, 0x51, 0x91, 0x0F, 0x1D, 0x79, 0x34, 0xD6,
        0xE2, 0xAE, 0x17, 0x57, 0x65, 0x64, 0xE2, 0xBC
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 value[16] = {
        0xD3, 0x51, 0x91, 0x0F, 0x1D, 0x79, 0x34, 0xD6,
        0xE2, 0xAE, 0x17, 0x57, 0x65, 0x64, 0xE2, 0xBC
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct key_value expected = {0};
    expected.key_material = &key;
    struct key_value observed = {0};
    
    int result = kmip_decode_key_value(&ctx, KMIP_KEYFORMAT_RAW, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_key_value(KMIP_KEYFORMAT_RAW, &expected, &observed),
        result,
        __func__);
    kmip_free_key_value(&ctx, KMIP_KEYFORMAT_RAW, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_key_value_with_attributes(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[144] = {
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x88, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x10, 
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x17, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x6C, 
        0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x14,
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x4C, 0x65, 
        0x6E, 0x67, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[144] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    uint8 value[16] = {
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct attribute attributes[2] = {{0}};
    for(int i = 0; i < 2; i++)
    {
        kmip_init_attribute(&attributes[i]);
    }
    
    enum cryptographic_algorithm ca = KMIP_CRYPTOALG_AES;
    int length = 128;
    attributes[0].type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    attributes[0].value = &ca;
    attributes[1].type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    attributes[1].value = &length;
    
    struct key_value kv = {0};
    kv.key_material = &key;
    kv.attributes = attributes;
    kv.attribute_count = ARRAY_LENGTH(attributes);
    
    int result = kmip_encode_key_value(&ctx, KMIP_KEYFORMAT_RAW, &kv);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_key_value_with_attributes(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[144] = {
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x88, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x10, 
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x17, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x6C, 
        0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x14,
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x4C, 0x65, 
        0x6E, 0x67, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 value[16] = {
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct attribute attributes[2] = {{0}};
    for(size_t i = 0; i < 2; i++)
    {
        kmip_init_attribute(&attributes[i]);
    }
    
    enum cryptographic_algorithm ca = KMIP_CRYPTOALG_AES;
    int length = 128;
    attributes[0].type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    attributes[0].value = &ca;
    attributes[1].type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    attributes[1].value = &length;
    
    struct key_value expected = {0};
    expected.key_material = &key;
    expected.attributes = attributes;
    expected.attribute_count = ARRAY_LENGTH(attributes);
    struct key_value observed = {0};
    
    int result = kmip_decode_key_value(&ctx, KMIP_KEYFORMAT_RAW, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_key_value(KMIP_KEYFORMAT_RAW, &expected, &observed),
        result,
        __func__);
    kmip_free_key_value(&ctx, KMIP_KEYFORMAT_RAW, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_key_block_key_value_byte_string(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[192] = {
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0xB8, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x08, 0x00, 0x00, 0x00, 0x18, 
        0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47, 
        0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82, 
        0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x46, 0x01, 0x00, 0x00, 0x00, 0x60, 
        0x42, 0x00, 0x9E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x36, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24,
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35, 
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D, 
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10, 
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[192] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    uint8 value[24] = {
        0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47,
        0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82,
        0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct text_string uuid = {0};
    uuid.value = "100182d5-72b8-47aa-8383-4d97d512e98a";
    uuid.size = 36;
    
    struct cryptographic_parameters cp = {0};
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;
    
    struct encryption_key_information eki = {0};
    eki.unique_identifier = &uuid;
    eki.cryptographic_parameters = &cp;
    
    struct key_wrapping_data kwd = {0};
    kwd.wrapping_method = KMIP_WRAP_ENCRYPT;
    kwd.encryption_key_info = &eki;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_RAW;
    kb.key_value = &key;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_AES;
    kb.cryptographic_length = 128;
    kb.key_wrapping_data = &kwd;
    
    int result = kmip_encode_key_block(&ctx, &kb);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_key_block_key_value_byte_string(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[192] = {
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0xB8, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x08, 0x00, 0x00, 0x00, 0x18, 
        0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47, 
        0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82, 
        0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x46, 0x01, 0x00, 0x00, 0x00, 0x60, 
        0x42, 0x00, 0x9E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x36, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24,
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35, 
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D, 
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10, 
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 value[24] = {
        0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47,
        0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82,
        0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct text_string uuid = {0};
    uuid.value = "100182d5-72b8-47aa-8383-4d97d512e98a";
    uuid.size = 36;
    
    struct cryptographic_parameters cp = {0};
    kmip_init_cryptographic_parameters(&cp);
    
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;
    
    struct encryption_key_information eki = {0};
    eki.unique_identifier = &uuid;
    eki.cryptographic_parameters = &cp;
    
    struct key_wrapping_data kwd = {0};
    kwd.wrapping_method = KMIP_WRAP_ENCRYPT;
    kwd.encryption_key_info = &eki;
    
    struct key_block expected = {0};
    kmip_init_key_block(&expected);
    
    expected.key_format_type = KMIP_KEYFORMAT_RAW;
    expected.key_value = &key;
    expected.key_value_type = KMIP_TYPE_BYTE_STRING;
    expected.cryptographic_algorithm = KMIP_CRYPTOALG_AES;
    expected.cryptographic_length = 128;
    expected.key_wrapping_data = &kwd;
    
    struct key_block observed = {0};
    kmip_init_key_block(&observed);
    
    int result = kmip_decode_key_block(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_key_block(&expected, &observed),
        result,
        __func__);
    kmip_free_key_block(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_key_block_key_value_structure(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[88] = {
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x50, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x18, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x10, 
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[88] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    uint8 value[16] = {
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &key;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_RAW;
    kb.key_value = &kv;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_AES;
    kb.cryptographic_length = 128;
    
    int result = kmip_encode_key_block(&ctx, &kb);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_key_block_key_value_structure(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[88] = {
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x50, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x18, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x10, 
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 value[16] = {
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &key;
    
    struct key_block expected = {0};
    kmip_init_key_block(&expected);
    
    expected.key_format_type = KMIP_KEYFORMAT_RAW;
    expected.key_value = &kv;
    expected.key_value_type = KMIP_TYPE_STRUCTURE;
    expected.cryptographic_algorithm = KMIP_CRYPTOALG_AES;
    expected.cryptographic_length = 128;
    
    struct key_block observed = {0};
    kmip_init_key_block(&observed);
    
    int result = kmip_decode_key_block(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_key_block(&expected, &observed),
        result,
        __func__);
    kmip_free_key_block(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_symmetric_key(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[96] = {
        0x42, 0x00, 0x8F, 0x01, 0x00, 0x00, 0x00, 0x58, 
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x50, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x18, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x10, 
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
        0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[96] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    uint8 value[16] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &key;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_RAW;
    kb.key_value = &kv;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_AES;
    kb.cryptographic_length = 128;
    
    struct symmetric_key sk = {0};
    sk.key_block = &kb;
    
    int result = kmip_encode_symmetric_key(&ctx, &sk);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_symmetric_key(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[96] = {
        0x42, 0x00, 0x8F, 0x01, 0x00, 0x00, 0x00, 0x58, 
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x50, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x18, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x10, 
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
        0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 value[16] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &key;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_RAW;
    kb.key_value = &kv;
    kb.key_value_type = KMIP_TYPE_STRUCTURE;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_AES;
    kb.cryptographic_length = 128;
    
    struct symmetric_key expected = {0};
    expected.key_block = &kb;
    
    struct symmetric_key observed = {0};
    
    int result = kmip_decode_symmetric_key(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_symmetric_key(&expected, &observed),
        result,
        __func__);
    kmip_free_symmetric_key(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_public_key(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[248] = {
        0x42, 0x00, 0x6D, 0x01, 0x00, 0x00, 0x00, 0xF0, 
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0xE8, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0xB0, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0xA2,
        0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A,
        0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 
        0x05, 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 
        0x89, 0x02, 0x81, 0x81, 0x00, 0x93, 0x04, 0x51,
        0xC9, 0xEC, 0xD9, 0x4F, 0x5B, 0xB9, 0xDA, 0x17, 
        0xDD, 0x09, 0x38, 0x1B, 0xD2, 0x3B, 0xE4, 0x3E, 
        0xCA, 0x8C, 0x75, 0x39, 0xF3, 0x01, 0xFC, 0x8A, 
        0x8C, 0xD5, 0xD5, 0x27, 0x4C, 0x3E, 0x76, 0x99, 
        0xDB, 0xDC, 0x71, 0x1C, 0x97, 0xA7, 0xAA, 0x91, 
        0xE2, 0xC5, 0x0A, 0x82, 0xBD, 0x0B, 0x10, 0x34, 
        0xF0, 0xDF, 0x49, 0x3D, 0xEC, 0x16, 0x36, 0x24,
        0x27, 0xE5, 0x8A, 0xCC, 0xE7, 0xF6, 0xCE, 0x0F, 
        0x9B, 0xCC, 0x61, 0x7B, 0xBD, 0x8C, 0x90, 0xD0, 
        0x09, 0x4A, 0x27, 0x03, 0xBA, 0x0D, 0x09, 0xEB, 
        0x19, 0xD1, 0x00, 0x5F, 0x2F, 0xB2, 0x65, 0x52, 
        0x6A, 0xAC, 0x75, 0xAF, 0x32, 0xF8, 0xBC, 0x78, 
        0x2C, 0xDE, 0xD2, 0xA5, 0x7F, 0x81, 0x1E, 0x03,
        0xEA, 0xF6, 0x7A, 0x94, 0x4D, 0xE5, 0xE7, 0x84, 
        0x13, 0xDC, 0xA8, 0xF2, 0x32, 0xD0, 0x74, 0xE6,
        0xDC, 0xEA, 0x4C, 0xEC, 0x9F, 0x02, 0x03, 0x01, 
        0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[248] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    uint8 value[162] = {
        0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A, 
        0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 
        0x05, 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 
        0x89, 0x02, 0x81, 0x81, 0x00, 0x93, 0x04, 0x51,
        0xC9, 0xEC, 0xD9, 0x4F, 0x5B, 0xB9, 0xDA, 0x17, 
        0xDD, 0x09, 0x38, 0x1B, 0xD2, 0x3B, 0xE4, 0x3E, 
        0xCA, 0x8C, 0x75, 0x39, 0xF3, 0x01, 0xFC, 0x8A, 
        0x8C, 0xD5, 0xD5, 0x27, 0x4C, 0x3E, 0x76, 0x99,
        0xDB, 0xDC, 0x71, 0x1C, 0x97, 0xA7, 0xAA, 0x91, 
        0xE2, 0xC5, 0x0A, 0x82, 0xBD, 0x0B, 0x10, 0x34, 
        0xF0, 0xDF, 0x49, 0x3D, 0xEC, 0x16, 0x36, 0x24, 
        0x27, 0xE5, 0x8A, 0xCC, 0xE7, 0xF6, 0xCE, 0x0F, 
        0x9B, 0xCC, 0x61, 0x7B, 0xBD, 0x8C, 0x90, 0xD0, 
        0x09, 0x4A, 0x27, 0x03, 0xBA, 0x0D, 0x09, 0xEB, 
        0x19, 0xD1, 0x00, 0x5F, 0x2F, 0xB2, 0x65, 0x52, 
        0x6A, 0xAC, 0x75, 0xAF, 0x32, 0xF8, 0xBC, 0x78, 
        0x2C, 0xDE, 0xD2, 0xA5, 0x7F, 0x81, 0x1E, 0x03, 
        0xEA, 0xF6, 0x7A, 0x94, 0x4D, 0xE5, 0xE7, 0x84,
        0x13, 0xDC, 0xA8, 0xF2, 0x32, 0xD0, 0x74, 0xE6,
        0xDC, 0xEA, 0x4C, 0xEC, 0x9F, 0x02, 0x03, 0x01,
        0x00, 0x01
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &key;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_X509;
    kb.key_value = &kv;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_RSA;
    kb.cryptographic_length = 1024;
    
    struct public_key pk = {0};
    pk.key_block = &kb;
    
    int result = kmip_encode_public_key(&ctx, &pk);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_public_key(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[248] = {
        0x42, 0x00, 0x6D, 0x01, 0x00, 0x00, 0x00, 0xF0, 
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0xE8, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0xB0, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0xA2,
        0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A,
        0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 
        0x05, 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 
        0x89, 0x02, 0x81, 0x81, 0x00, 0x93, 0x04, 0x51,
        0xC9, 0xEC, 0xD9, 0x4F, 0x5B, 0xB9, 0xDA, 0x17, 
        0xDD, 0x09, 0x38, 0x1B, 0xD2, 0x3B, 0xE4, 0x3E, 
        0xCA, 0x8C, 0x75, 0x39, 0xF3, 0x01, 0xFC, 0x8A, 
        0x8C, 0xD5, 0xD5, 0x27, 0x4C, 0x3E, 0x76, 0x99, 
        0xDB, 0xDC, 0x71, 0x1C, 0x97, 0xA7, 0xAA, 0x91, 
        0xE2, 0xC5, 0x0A, 0x82, 0xBD, 0x0B, 0x10, 0x34, 
        0xF0, 0xDF, 0x49, 0x3D, 0xEC, 0x16, 0x36, 0x24,
        0x27, 0xE5, 0x8A, 0xCC, 0xE7, 0xF6, 0xCE, 0x0F, 
        0x9B, 0xCC, 0x61, 0x7B, 0xBD, 0x8C, 0x90, 0xD0, 
        0x09, 0x4A, 0x27, 0x03, 0xBA, 0x0D, 0x09, 0xEB, 
        0x19, 0xD1, 0x00, 0x5F, 0x2F, 0xB2, 0x65, 0x52, 
        0x6A, 0xAC, 0x75, 0xAF, 0x32, 0xF8, 0xBC, 0x78, 
        0x2C, 0xDE, 0xD2, 0xA5, 0x7F, 0x81, 0x1E, 0x03,
        0xEA, 0xF6, 0x7A, 0x94, 0x4D, 0xE5, 0xE7, 0x84, 
        0x13, 0xDC, 0xA8, 0xF2, 0x32, 0xD0, 0x74, 0xE6,
        0xDC, 0xEA, 0x4C, 0xEC, 0x9F, 0x02, 0x03, 0x01, 
        0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 value[162] = {
        0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A, 
        0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 
        0x05, 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 
        0x89, 0x02, 0x81, 0x81, 0x00, 0x93, 0x04, 0x51,
        0xC9, 0xEC, 0xD9, 0x4F, 0x5B, 0xB9, 0xDA, 0x17, 
        0xDD, 0x09, 0x38, 0x1B, 0xD2, 0x3B, 0xE4, 0x3E, 
        0xCA, 0x8C, 0x75, 0x39, 0xF3, 0x01, 0xFC, 0x8A, 
        0x8C, 0xD5, 0xD5, 0x27, 0x4C, 0x3E, 0x76, 0x99,
        0xDB, 0xDC, 0x71, 0x1C, 0x97, 0xA7, 0xAA, 0x91, 
        0xE2, 0xC5, 0x0A, 0x82, 0xBD, 0x0B, 0x10, 0x34, 
        0xF0, 0xDF, 0x49, 0x3D, 0xEC, 0x16, 0x36, 0x24, 
        0x27, 0xE5, 0x8A, 0xCC, 0xE7, 0xF6, 0xCE, 0x0F, 
        0x9B, 0xCC, 0x61, 0x7B, 0xBD, 0x8C, 0x90, 0xD0, 
        0x09, 0x4A, 0x27, 0x03, 0xBA, 0x0D, 0x09, 0xEB, 
        0x19, 0xD1, 0x00, 0x5F, 0x2F, 0xB2, 0x65, 0x52, 
        0x6A, 0xAC, 0x75, 0xAF, 0x32, 0xF8, 0xBC, 0x78, 
        0x2C, 0xDE, 0xD2, 0xA5, 0x7F, 0x81, 0x1E, 0x03, 
        0xEA, 0xF6, 0x7A, 0x94, 0x4D, 0xE5, 0xE7, 0x84,
        0x13, 0xDC, 0xA8, 0xF2, 0x32, 0xD0, 0x74, 0xE6,
        0xDC, 0xEA, 0x4C, 0xEC, 0x9F, 0x02, 0x03, 0x01,
        0x00, 0x01
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &key;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_X509;
    kb.key_value = &kv;
    kb.key_value_type = KMIP_TYPE_STRUCTURE;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_RSA;
    kb.cryptographic_length = 1024;
    
    struct public_key expected = {0};
    expected.key_block = &kb;
    
    struct public_key observed = {0};
    
    int result = kmip_decode_public_key(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_public_key(&expected, &observed),
        result,
        __func__);
    kmip_free_public_key(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_private_key(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[1280] = {
        0x42, 0x00, 0x64, 0x01, 0x00, 0x00, 0x04, 0xF8, 
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x04, 0xF0, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x04, 0xB8, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x04, 0xA9,
        0x30, 0x82, 0x04, 0xA5, 0x02, 0x01, 0x00, 0x02, 
        0x82, 0x01, 0x01, 0x00, 0xAB, 0x7F, 0x16, 0x1C, 
        0x00, 0x42, 0x49, 0x6C, 0xCD, 0x6C, 0x6D, 0x4D, 
        0xAD, 0xB9, 0x19, 0x97, 0x34, 0x35, 0x35, 0x77, 
        0x76, 0x00, 0x3A, 0xCF, 0x54, 0xB7, 0xAF, 0x1E, 
        0x44, 0x0A, 0xFB, 0x80, 0xB6, 0x4A, 0x87, 0x55, 
        0xF8, 0x00, 0x2C, 0xFE, 0xBA, 0x6B, 0x18, 0x45, 
        0x40, 0xA2, 0xD6, 0x60, 0x86, 0xD7, 0x46, 0x48, 
        0x34, 0x6D, 0x75, 0xB8, 0xD7, 0x18, 0x12, 0xB2, 
        0x05, 0x38, 0x7C, 0x0F, 0x65, 0x83, 0xBC, 0x4D, 
        0x7D, 0xC7, 0xEC, 0x11, 0x4F, 0x3B, 0x17, 0x6B, 
        0x79, 0x57, 0xC4, 0x22, 0xE7, 0xD0, 0x3F, 0xC6,
        0x26, 0x7F, 0xA2, 0xA6, 0xF8, 0x9B, 0x9B, 0xEE, 
        0x9E, 0x60, 0xA1, 0xD7, 0xC2, 0xD8, 0x33, 0xE5, 
        0xA5, 0xF4, 0xBB, 0x0B, 0x14, 0x34, 0xF4, 0xE7, 
        0x95, 0xA4, 0x11, 0x00, 0xF8, 0xAA, 0x21, 0x49, 
        0x00, 0xDF, 0x8B, 0x65, 0x08, 0x9F, 0x98, 0x13, 
        0x5B, 0x1C, 0x67, 0xB7, 0x01, 0x67, 0x5A, 0xBD, 
        0xBC, 0x7D, 0x57, 0x21, 0xAA, 0xC9, 0xD1, 0x4A, 
        0x7F, 0x08, 0x1F, 0xCE, 0xC8, 0x0B, 0x64, 0xE8, 
        0xA0, 0xEC, 0xC8, 0x29, 0x53, 0x53, 0xC7, 0x95, 
        0x32, 0x8A, 0xBF, 0x70, 0xE1, 0xB4, 0x2E, 0x7B, 
        0xB8, 0xB7, 0xF4, 0xE8, 0xAC, 0x8C, 0x81, 0x0C, 
        0xDB, 0x66, 0xE3, 0xD2, 0x11, 0x26, 0xEB, 0xA8, 
        0xDA, 0x7D, 0x0C, 0xA3, 0x41, 0x42, 0xCB, 0x76, 
        0xF9, 0x1F, 0x01, 0x3D, 0xA8, 0x09, 0xE9, 0xC1, 
        0xB7, 0xAE, 0x64, 0xC5, 0x41, 0x30, 0xFB, 0xC2, 
        0x1D, 0x80, 0xE9, 0xC2, 0xCB, 0x06, 0xC5, 0xC8, 
        0xD7, 0xCC, 0xE8, 0x94, 0x6A, 0x9A, 0xC9, 0x9B,
        0x1C, 0x28, 0x15, 0xC3, 0x61, 0x2A, 0x29, 0xA8, 
        0x2D, 0x73, 0xA1, 0xF9, 0x93, 0x74, 0xFE, 0x30, 
        0xE5, 0x49, 0x51, 0x66, 0x2A, 0x6E, 0xDA, 0x29, 
        0xC6, 0xFC, 0x41, 0x13, 0x35, 0xD5, 0xDC, 0x74, 
        0x26, 0xB0, 0xF6, 0x05, 0x02, 0x03, 0x01, 0x00, 
        0x01, 0x02, 0x82, 0x01, 0x00, 0x3B, 0x12, 0x45, 
        0x5D, 0x53, 0xC1, 0x81, 0x65, 0x16, 0xC5, 0x18, 
        0x49, 0x3F, 0x63, 0x98, 0xAA, 0xFA, 0x72, 0xB1, 
        0x7D, 0xFA, 0x89, 0x4D, 0xB8, 0x88, 0xA7, 0xD4, 
        0x8C, 0x0A, 0x47, 0xF6, 0x25, 0x79, 0xA4, 0xE6, 
        0x44, 0xF8, 0x6D, 0xA7, 0x11, 0xFE, 0xC8, 0x50, 
        0xCD, 0xD9, 0xDB, 0xBD, 0x17, 0xF6, 0x9A, 0x44, 
        0x3D, 0x2E, 0xC1, 0xDD, 0x60, 0xD3, 0xC6, 0x18, 
        0xFA, 0x74, 0xCD, 0xE5, 0xFD, 0xAF, 0xAB, 0xD6, 
        0xBA, 0xA2, 0x6E, 0xB0, 0xA3, 0xAD, 0xB4, 0xDE, 
        0xF6, 0x48, 0x0F, 0xB1, 0x21, 0x8C, 0xD3, 0xB0,
        0x83, 0xE2, 0x52, 0xE8, 0x85, 0xB6, 0xF0, 0x72, 
        0x9F, 0x98, 0xB2, 0x14, 0x4D, 0x2B, 0x72, 0x29, 
        0x3E, 0x1B, 0x11, 0xD7, 0x33, 0x93, 0xBC, 0x41, 
        0xF7, 0x5B, 0x15, 0xEE, 0x3D, 0x75, 0x69, 0xB4, 
        0x99, 0x5E, 0xD1, 0xA1, 0x44, 0x25, 0xDA, 0x43, 
        0x19, 0xB7, 0xB2, 0x6B, 0x0E, 0x8F, 0xEF, 0x17, 
        0xC3, 0x75, 0x42, 0xAE, 0x5C, 0x6D, 0x58, 0x49, 
        0xF8, 0x72, 0x09, 0x56, 0x7F, 0x39, 0x25, 0xA4, 
        0x7B, 0x01, 0x6D, 0x56, 0x48, 0x59, 0x71, 0x7B, 
        0xC5, 0x7F, 0xCB, 0x45, 0x22, 0xD0, 0xAA, 0x49, 
        0xCE, 0x81, 0x6E, 0x5B, 0xE7, 0xB3, 0x08, 0x81, 
        0x93, 0x23, 0x6E, 0xC9, 0xEF, 0xFF, 0x14, 0x08, 
        0x58, 0x04, 0x5B, 0x73, 0xC5, 0xD7, 0x9B, 0xAF, 
        0x38, 0xF7, 0xC6, 0x7F, 0x04, 0xC5, 0xDC, 0xF0, 
        0xE3, 0x80, 0x6A, 0xD9, 0x82, 0xD1, 0x25, 0x90, 
        0x58, 0xC3, 0x47, 0x3E, 0x84, 0x71, 0x79, 0xA8, 
        0x78, 0xF2, 0xC6, 0xB3, 0xBD, 0x96, 0x8F, 0xB9,
        0x9E, 0xA4, 0x6E, 0x91, 0x85, 0x89, 0x2F, 0x36,
        0x76, 0xE7, 0x89, 0x65, 0xC2, 0xAE, 0xD4, 0x87,
        0x7B, 0xA3, 0x91, 0x7D, 0xF0, 0x7C, 0x5E, 0x92, 
        0x74, 0x74, 0xF1, 0x9E, 0x76, 0x4B, 0xA6, 0x1D, 
        0xC3, 0x8D, 0x63, 0xBF, 0x29, 0x02, 0x81, 0x81, 
        0x00, 0xD5, 0xC6, 0x9C, 0x8C, 0x3C, 0xDC, 0x24, 
        0x64, 0x74, 0x4A, 0x79, 0x37, 0x13, 0xDA, 0xFB, 
        0x9F, 0x1D, 0xBC, 0x79, 0x9F, 0xF9, 0x64, 0x23, 
        0xFE, 0xCD, 0x3C, 0xBA, 0x79, 0x42, 0x86, 0xBC, 
        0xE9, 0x20, 0xF4, 0xB5, 0xC1, 0x83, 0xF9, 0x9E, 
        0xE9, 0x02, 0x8D, 0xB6, 0x21, 0x2C, 0x62, 0x77, 
        0xC4, 0xC8, 0x29, 0x7F, 0xCF, 0xBC, 0xE7, 0xF7,
        0xC2, 0x4C, 0xA4, 0xC5, 0x1F, 0xC7, 0x18, 0x2F, 
        0xB8, 0xF4, 0x01, 0x9F, 0xB1, 0xD5, 0x65, 0x96, 
        0x74, 0xC5, 0xCB, 0xE6, 0xD5, 0xFA, 0x99, 0x20, 
        0x51, 0x34, 0x17, 0x60, 0xCD, 0x00, 0x73, 0x57, 
        0x29, 0xA0, 0x70, 0xA9, 0xE5, 0x4D, 0x34, 0x2B, 
        0xEB, 0xA8, 0xEF, 0x47, 0xEE, 0x82, 0xD3, 0xA0, 
        0x1B, 0x04, 0xCE, 0xC4, 0xA0, 0x0D, 0x4D, 0xDB,
        0x41, 0xE3, 0x51, 0x16, 0xFC, 0x22, 0x1E, 0x85, 
        0x4B, 0x43, 0xA6, 0x96, 0xC0, 0xE6, 0x41, 0x9B, 
        0x1B, 0x02, 0x81, 0x81, 0x00, 0xCD, 0x5E, 0xA7, 
        0x70, 0x27, 0x89, 0x06, 0x4B, 0x67, 0x35, 0x40, 
        0xCB, 0xFF, 0x09, 0x35, 0x6A, 0xD8, 0x0B, 0xC3, 
        0xD5, 0x92, 0x81, 0x2E, 0xBA, 0x47, 0x61, 0x0B,
        0x9F, 0xAC, 0x6A, 0xEC, 0xEF, 0xE2, 0x2A, 0xCA, 
        0xE4, 0x38, 0x45, 0x9C, 0xDA, 0x74, 0xE5, 0x96, 
        0x53, 0xD8, 0x8C, 0x04, 0x18, 0x9D, 0x34, 0x39, 
        0x9B, 0xF5, 0xB1, 0x4B, 0x92, 0x0E, 0x34, 0xEF, 
        0x38, 0xA7, 0xD0, 0x9F, 0xE6, 0x95, 0x93, 0x39, 
        0x6E, 0x8F, 0xE7, 0x35, 0xE6, 0xF0, 0xA6, 0xAE, 
        0x49, 0x90, 0x40, 0x10, 0x41, 0xD8, 0xA4, 0x06, 
        0xB6, 0xFD, 0x86, 0xA1, 0x16, 0x1E, 0x45, 0xF9,
        0x5A, 0x3E, 0xAA, 0x5C, 0x10, 0x12, 0xE6, 0x66,
        0x2E, 0x44, 0xF1, 0x5F, 0x33, 0x5A, 0xC9, 0x71, 
        0xE1, 0x76, 0x6B, 0x2B, 0xB9, 0xC9, 0x85, 0x10, 
        0x99, 0x74, 0x14, 0x1B, 0x44, 0xD3, 0x7E, 0x1E, 
        0x31, 0x98, 0x20, 0xA5, 0x5F, 0x02, 0x81, 0x81, 
        0x00, 0xB2, 0x87, 0x12, 0x37, 0xBF, 0x9F, 0xAD, 
        0x38, 0xC3, 0x31, 0x6A, 0xB7, 0x87, 0x7A, 0x6A, 
        0x86, 0x80, 0x63, 0xE5, 0x42, 0xA7, 0x18, 0x6D, 
        0x43, 0x1E, 0x8D, 0x27, 0xC1, 0x9A, 0xC0, 0x41, 
        0x45, 0x84, 0x03, 0x39, 0x42, 0xE9, 0xFF, 0x6E, 
        0x29, 0x73, 0xBB, 0x7B, 0x2D, 0x8B, 0x0E, 0x94, 
        0xAD, 0x1E, 0xE8, 0x21, 0x58, 0x10, 0x8F, 0xBC,
        0x86, 0x64, 0x51, 0x7A, 0x5A, 0x46, 0x7F, 0xB9, 
        0x63, 0x01, 0x4B, 0xD5, 0xDC, 0xC2, 0xB4, 0xFB, 
        0x08, 0x7C, 0x23, 0x03, 0x9D, 0x11, 0x92, 0x0D, 
        0xBE, 0x22, 0xFD, 0x9F, 0x16, 0xB4, 0xD8, 0x9E, 
        0x23, 0x22, 0x5C, 0xD4, 0x55, 0xAD, 0xBA, 0xF3, 
        0x2E, 0xF4, 0x3F, 0x18, 0x58, 0x64, 0xA3, 0x6D,
        0x63, 0x03, 0x09, 0xD6, 0x85, 0x3F, 0x77, 0x14,
        0xB3, 0x9A, 0xAE, 0x1E, 0xBE, 0xE3, 0x93, 0x8F, 
        0x87, 0xC2, 0x70, 0x7E, 0x17, 0x8C, 0x73, 0x9F, 
        0x9F, 0x02, 0x81, 0x81, 0x00, 0x96, 0x90, 0xBE,
        0xD1, 0x4B, 0x2A, 0xFA, 0xA2, 0x6D, 0x98, 0x6D, 
        0x59, 0x22, 0x31, 0xEE, 0x27, 0xD7, 0x1D, 0x49, 
        0x06, 0x5B, 0xD2, 0xBA, 0x1F, 0x78, 0x15, 0x7E, 
        0x20, 0x22, 0x98, 0x81, 0xFD, 0x9D, 0x23, 0x22, 
        0x7D, 0x0F, 0x84, 0x79, 0xEA, 0xEF, 0xA9, 0x22, 
        0xFD, 0x75, 0xD5, 0xB1, 0x6B, 0x1A, 0x56, 0x1F,
        0xA6, 0x68, 0x0B, 0x04, 0x0C, 0xA0, 0xBD, 0xCE, 
        0x65, 0x0B, 0x23, 0xB9, 0x17, 0xA4, 0xB1, 0xBB, 
        0x79, 0x83, 0xA7, 0x4F, 0xAD, 0x70, 0xE1, 0xC3, 
        0x05, 0xCB, 0xEC, 0x2B, 0xFF, 0x1A, 0x85, 0xA7,
        0x26, 0xA1, 0xD9, 0x02, 0x60, 0xE4, 0xF1, 0x08, 
        0x4F, 0x51, 0x82, 0x34, 0xDC, 0xD3, 0xFE, 0x77, 
        0x0B, 0x95, 0x20, 0x21, 0x5B, 0xD5, 0x43, 0xBB, 
        0x6A, 0x41, 0x17, 0x71, 0x87, 0x54, 0x67, 0x6A, 
        0x34, 0x17, 0x16, 0x66, 0xA7, 0x9F, 0x26, 0xE7, 
        0x9C, 0x14, 0x9C, 0x5A, 0xA1, 0x02, 0x81, 0x81, 
        0x00, 0xA0, 0xC9, 0x85, 0xA0, 0xA0, 0xA7, 0x91, 
        0xA6, 0x59, 0xF9, 0x97, 0x31, 0x13, 0x4C, 0x44, 
        0xF3, 0x7B, 0x2E, 0x52, 0x0A, 0x2C, 0xEA, 0x35, 
        0x80, 0x0A, 0xD2, 0x72, 0x41, 0xED, 0x36, 0x0D, 
        0xFD, 0xE6, 0xE8, 0xCA, 0x61, 0x4F, 0x12, 0x04, 
        0x7F, 0xD0, 0x8B, 0x76, 0xAC, 0x4D, 0x13, 0xC0, 
        0x56, 0xA0, 0x69, 0x9E, 0x2F, 0x98, 0xA1, 0xCA, 
        0xC9, 0x10, 0x11, 0x29, 0x4D, 0x71, 0x20, 0x8F, 
        0x4A, 0xBA, 0xB3, 0x3B, 0xA8, 0x7A, 0xA0, 0x51, 
        0x7F, 0x41, 0x5B, 0xAC, 0xA8, 0x8D, 0x6B, 0xAC, 
        0x00, 0x60, 0x88, 0xFA, 0x60, 0x1D, 0x34, 0x94, 
        0x17, 0xE1, 0xF0, 0xC9, 0xB2, 0x3A, 0xFF, 0xA4, 
        0xD4, 0x96, 0x61, 0x8D, 0xBC, 0x02, 0x49, 0x86, 
        0xED, 0x69, 0x0B, 0xBB, 0x7B, 0x02, 0x57, 0x68, 
        0xFF, 0x9D, 0xF8, 0xAC, 0x15, 0x41, 0x6F, 0x48, 
        0x9F, 0x81, 0x29, 0xC3, 0x23, 0x41, 0xA8, 0xB4, 
        0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[1280] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    uint8 value[1193] = {
        0x30, 0x82, 0x04, 0xA5, 0x02, 0x01, 0x00, 0x02, 
        0x82, 0x01, 0x01, 0x00, 0xAB, 0x7F, 0x16, 0x1C, 
        0x00, 0x42, 0x49, 0x6C, 0xCD, 0x6C, 0x6D, 0x4D, 
        0xAD, 0xB9, 0x19, 0x97, 0x34, 0x35, 0x35, 0x77, 
        0x76, 0x00, 0x3A, 0xCF, 0x54, 0xB7, 0xAF, 0x1E, 
        0x44, 0x0A, 0xFB, 0x80, 0xB6, 0x4A, 0x87, 0x55, 
        0xF8, 0x00, 0x2C, 0xFE, 0xBA, 0x6B, 0x18, 0x45, 
        0x40, 0xA2, 0xD6, 0x60, 0x86, 0xD7, 0x46, 0x48, 
        0x34, 0x6D, 0x75, 0xB8, 0xD7, 0x18, 0x12, 0xB2, 
        0x05, 0x38, 0x7C, 0x0F, 0x65, 0x83, 0xBC, 0x4D, 
        0x7D, 0xC7, 0xEC, 0x11, 0x4F, 0x3B, 0x17, 0x6B, 
        0x79, 0x57, 0xC4, 0x22, 0xE7, 0xD0, 0x3F, 0xC6,
        0x26, 0x7F, 0xA2, 0xA6, 0xF8, 0x9B, 0x9B, 0xEE, 
        0x9E, 0x60, 0xA1, 0xD7, 0xC2, 0xD8, 0x33, 0xE5, 
        0xA5, 0xF4, 0xBB, 0x0B, 0x14, 0x34, 0xF4, 0xE7, 
        0x95, 0xA4, 0x11, 0x00, 0xF8, 0xAA, 0x21, 0x49, 
        0x00, 0xDF, 0x8B, 0x65, 0x08, 0x9F, 0x98, 0x13, 
        0x5B, 0x1C, 0x67, 0xB7, 0x01, 0x67, 0x5A, 0xBD, 
        0xBC, 0x7D, 0x57, 0x21, 0xAA, 0xC9, 0xD1, 0x4A, 
        0x7F, 0x08, 0x1F, 0xCE, 0xC8, 0x0B, 0x64, 0xE8, 
        0xA0, 0xEC, 0xC8, 0x29, 0x53, 0x53, 0xC7, 0x95, 
        0x32, 0x8A, 0xBF, 0x70, 0xE1, 0xB4, 0x2E, 0x7B, 
        0xB8, 0xB7, 0xF4, 0xE8, 0xAC, 0x8C, 0x81, 0x0C, 
        0xDB, 0x66, 0xE3, 0xD2, 0x11, 0x26, 0xEB, 0xA8, 
        0xDA, 0x7D, 0x0C, 0xA3, 0x41, 0x42, 0xCB, 0x76, 
        0xF9, 0x1F, 0x01, 0x3D, 0xA8, 0x09, 0xE9, 0xC1, 
        0xB7, 0xAE, 0x64, 0xC5, 0x41, 0x30, 0xFB, 0xC2, 
        0x1D, 0x80, 0xE9, 0xC2, 0xCB, 0x06, 0xC5, 0xC8, 
        0xD7, 0xCC, 0xE8, 0x94, 0x6A, 0x9A, 0xC9, 0x9B,
        0x1C, 0x28, 0x15, 0xC3, 0x61, 0x2A, 0x29, 0xA8, 
        0x2D, 0x73, 0xA1, 0xF9, 0x93, 0x74, 0xFE, 0x30, 
        0xE5, 0x49, 0x51, 0x66, 0x2A, 0x6E, 0xDA, 0x29, 
        0xC6, 0xFC, 0x41, 0x13, 0x35, 0xD5, 0xDC, 0x74, 
        0x26, 0xB0, 0xF6, 0x05, 0x02, 0x03, 0x01, 0x00, 
        0x01, 0x02, 0x82, 0x01, 0x00, 0x3B, 0x12, 0x45, 
        0x5D, 0x53, 0xC1, 0x81, 0x65, 0x16, 0xC5, 0x18, 
        0x49, 0x3F, 0x63, 0x98, 0xAA, 0xFA, 0x72, 0xB1, 
        0x7D, 0xFA, 0x89, 0x4D, 0xB8, 0x88, 0xA7, 0xD4, 
        0x8C, 0x0A, 0x47, 0xF6, 0x25, 0x79, 0xA4, 0xE6, 
        0x44, 0xF8, 0x6D, 0xA7, 0x11, 0xFE, 0xC8, 0x50, 
        0xCD, 0xD9, 0xDB, 0xBD, 0x17, 0xF6, 0x9A, 0x44, 
        0x3D, 0x2E, 0xC1, 0xDD, 0x60, 0xD3, 0xC6, 0x18, 
        0xFA, 0x74, 0xCD, 0xE5, 0xFD, 0xAF, 0xAB, 0xD6, 
        0xBA, 0xA2, 0x6E, 0xB0, 0xA3, 0xAD, 0xB4, 0xDE, 
        0xF6, 0x48, 0x0F, 0xB1, 0x21, 0x8C, 0xD3, 0xB0,
        0x83, 0xE2, 0x52, 0xE8, 0x85, 0xB6, 0xF0, 0x72, 
        0x9F, 0x98, 0xB2, 0x14, 0x4D, 0x2B, 0x72, 0x29, 
        0x3E, 0x1B, 0x11, 0xD7, 0x33, 0x93, 0xBC, 0x41, 
        0xF7, 0x5B, 0x15, 0xEE, 0x3D, 0x75, 0x69, 0xB4, 
        0x99, 0x5E, 0xD1, 0xA1, 0x44, 0x25, 0xDA, 0x43, 
        0x19, 0xB7, 0xB2, 0x6B, 0x0E, 0x8F, 0xEF, 0x17, 
        0xC3, 0x75, 0x42, 0xAE, 0x5C, 0x6D, 0x58, 0x49, 
        0xF8, 0x72, 0x09, 0x56, 0x7F, 0x39, 0x25, 0xA4, 
        0x7B, 0x01, 0x6D, 0x56, 0x48, 0x59, 0x71, 0x7B, 
        0xC5, 0x7F, 0xCB, 0x45, 0x22, 0xD0, 0xAA, 0x49, 
        0xCE, 0x81, 0x6E, 0x5B, 0xE7, 0xB3, 0x08, 0x81, 
        0x93, 0x23, 0x6E, 0xC9, 0xEF, 0xFF, 0x14, 0x08, 
        0x58, 0x04, 0x5B, 0x73, 0xC5, 0xD7, 0x9B, 0xAF, 
        0x38, 0xF7, 0xC6, 0x7F, 0x04, 0xC5, 0xDC, 0xF0, 
        0xE3, 0x80, 0x6A, 0xD9, 0x82, 0xD1, 0x25, 0x90, 
        0x58, 0xC3, 0x47, 0x3E, 0x84, 0x71, 0x79, 0xA8, 
        0x78, 0xF2, 0xC6, 0xB3, 0xBD, 0x96, 0x8F, 0xB9,
        0x9E, 0xA4, 0x6E, 0x91, 0x85, 0x89, 0x2F, 0x36,
        0x76, 0xE7, 0x89, 0x65, 0xC2, 0xAE, 0xD4, 0x87,
        0x7B, 0xA3, 0x91, 0x7D, 0xF0, 0x7C, 0x5E, 0x92, 
        0x74, 0x74, 0xF1, 0x9E, 0x76, 0x4B, 0xA6, 0x1D, 
        0xC3, 0x8D, 0x63, 0xBF, 0x29, 0x02, 0x81, 0x81, 
        0x00, 0xD5, 0xC6, 0x9C, 0x8C, 0x3C, 0xDC, 0x24, 
        0x64, 0x74, 0x4A, 0x79, 0x37, 0x13, 0xDA, 0xFB, 
        0x9F, 0x1D, 0xBC, 0x79, 0x9F, 0xF9, 0x64, 0x23, 
        0xFE, 0xCD, 0x3C, 0xBA, 0x79, 0x42, 0x86, 0xBC, 
        0xE9, 0x20, 0xF4, 0xB5, 0xC1, 0x83, 0xF9, 0x9E, 
        0xE9, 0x02, 0x8D, 0xB6, 0x21, 0x2C, 0x62, 0x77, 
        0xC4, 0xC8, 0x29, 0x7F, 0xCF, 0xBC, 0xE7, 0xF7,
        0xC2, 0x4C, 0xA4, 0xC5, 0x1F, 0xC7, 0x18, 0x2F, 
        0xB8, 0xF4, 0x01, 0x9F, 0xB1, 0xD5, 0x65, 0x96, 
        0x74, 0xC5, 0xCB, 0xE6, 0xD5, 0xFA, 0x99, 0x20, 
        0x51, 0x34, 0x17, 0x60, 0xCD, 0x00, 0x73, 0x57, 
        0x29, 0xA0, 0x70, 0xA9, 0xE5, 0x4D, 0x34, 0x2B, 
        0xEB, 0xA8, 0xEF, 0x47, 0xEE, 0x82, 0xD3, 0xA0, 
        0x1B, 0x04, 0xCE, 0xC4, 0xA0, 0x0D, 0x4D, 0xDB,
        0x41, 0xE3, 0x51, 0x16, 0xFC, 0x22, 0x1E, 0x85, 
        0x4B, 0x43, 0xA6, 0x96, 0xC0, 0xE6, 0x41, 0x9B, 
        0x1B, 0x02, 0x81, 0x81, 0x00, 0xCD, 0x5E, 0xA7, 
        0x70, 0x27, 0x89, 0x06, 0x4B, 0x67, 0x35, 0x40, 
        0xCB, 0xFF, 0x09, 0x35, 0x6A, 0xD8, 0x0B, 0xC3, 
        0xD5, 0x92, 0x81, 0x2E, 0xBA, 0x47, 0x61, 0x0B,
        0x9F, 0xAC, 0x6A, 0xEC, 0xEF, 0xE2, 0x2A, 0xCA, 
        0xE4, 0x38, 0x45, 0x9C, 0xDA, 0x74, 0xE5, 0x96, 
        0x53, 0xD8, 0x8C, 0x04, 0x18, 0x9D, 0x34, 0x39, 
        0x9B, 0xF5, 0xB1, 0x4B, 0x92, 0x0E, 0x34, 0xEF, 
        0x38, 0xA7, 0xD0, 0x9F, 0xE6, 0x95, 0x93, 0x39, 
        0x6E, 0x8F, 0xE7, 0x35, 0xE6, 0xF0, 0xA6, 0xAE, 
        0x49, 0x90, 0x40, 0x10, 0x41, 0xD8, 0xA4, 0x06, 
        0xB6, 0xFD, 0x86, 0xA1, 0x16, 0x1E, 0x45, 0xF9,
        0x5A, 0x3E, 0xAA, 0x5C, 0x10, 0x12, 0xE6, 0x66,
        0x2E, 0x44, 0xF1, 0x5F, 0x33, 0x5A, 0xC9, 0x71, 
        0xE1, 0x76, 0x6B, 0x2B, 0xB9, 0xC9, 0x85, 0x10, 
        0x99, 0x74, 0x14, 0x1B, 0x44, 0xD3, 0x7E, 0x1E, 
        0x31, 0x98, 0x20, 0xA5, 0x5F, 0x02, 0x81, 0x81, 
        0x00, 0xB2, 0x87, 0x12, 0x37, 0xBF, 0x9F, 0xAD, 
        0x38, 0xC3, 0x31, 0x6A, 0xB7, 0x87, 0x7A, 0x6A, 
        0x86, 0x80, 0x63, 0xE5, 0x42, 0xA7, 0x18, 0x6D, 
        0x43, 0x1E, 0x8D, 0x27, 0xC1, 0x9A, 0xC0, 0x41, 
        0x45, 0x84, 0x03, 0x39, 0x42, 0xE9, 0xFF, 0x6E, 
        0x29, 0x73, 0xBB, 0x7B, 0x2D, 0x8B, 0x0E, 0x94, 
        0xAD, 0x1E, 0xE8, 0x21, 0x58, 0x10, 0x8F, 0xBC,
        0x86, 0x64, 0x51, 0x7A, 0x5A, 0x46, 0x7F, 0xB9, 
        0x63, 0x01, 0x4B, 0xD5, 0xDC, 0xC2, 0xB4, 0xFB, 
        0x08, 0x7C, 0x23, 0x03, 0x9D, 0x11, 0x92, 0x0D, 
        0xBE, 0x22, 0xFD, 0x9F, 0x16, 0xB4, 0xD8, 0x9E, 
        0x23, 0x22, 0x5C, 0xD4, 0x55, 0xAD, 0xBA, 0xF3, 
        0x2E, 0xF4, 0x3F, 0x18, 0x58, 0x64, 0xA3, 0x6D,
        0x63, 0x03, 0x09, 0xD6, 0x85, 0x3F, 0x77, 0x14,
        0xB3, 0x9A, 0xAE, 0x1E, 0xBE, 0xE3, 0x93, 0x8F, 
        0x87, 0xC2, 0x70, 0x7E, 0x17, 0x8C, 0x73, 0x9F, 
        0x9F, 0x02, 0x81, 0x81, 0x00, 0x96, 0x90, 0xBE,
        0xD1, 0x4B, 0x2A, 0xFA, 0xA2, 0x6D, 0x98, 0x6D, 
        0x59, 0x22, 0x31, 0xEE, 0x27, 0xD7, 0x1D, 0x49, 
        0x06, 0x5B, 0xD2, 0xBA, 0x1F, 0x78, 0x15, 0x7E, 
        0x20, 0x22, 0x98, 0x81, 0xFD, 0x9D, 0x23, 0x22, 
        0x7D, 0x0F, 0x84, 0x79, 0xEA, 0xEF, 0xA9, 0x22, 
        0xFD, 0x75, 0xD5, 0xB1, 0x6B, 0x1A, 0x56, 0x1F,
        0xA6, 0x68, 0x0B, 0x04, 0x0C, 0xA0, 0xBD, 0xCE, 
        0x65, 0x0B, 0x23, 0xB9, 0x17, 0xA4, 0xB1, 0xBB, 
        0x79, 0x83, 0xA7, 0x4F, 0xAD, 0x70, 0xE1, 0xC3, 
        0x05, 0xCB, 0xEC, 0x2B, 0xFF, 0x1A, 0x85, 0xA7,
        0x26, 0xA1, 0xD9, 0x02, 0x60, 0xE4, 0xF1, 0x08, 
        0x4F, 0x51, 0x82, 0x34, 0xDC, 0xD3, 0xFE, 0x77, 
        0x0B, 0x95, 0x20, 0x21, 0x5B, 0xD5, 0x43, 0xBB, 
        0x6A, 0x41, 0x17, 0x71, 0x87, 0x54, 0x67, 0x6A, 
        0x34, 0x17, 0x16, 0x66, 0xA7, 0x9F, 0x26, 0xE7, 
        0x9C, 0x14, 0x9C, 0x5A, 0xA1, 0x02, 0x81, 0x81, 
        0x00, 0xA0, 0xC9, 0x85, 0xA0, 0xA0, 0xA7, 0x91, 
        0xA6, 0x59, 0xF9, 0x97, 0x31, 0x13, 0x4C, 0x44, 
        0xF3, 0x7B, 0x2E, 0x52, 0x0A, 0x2C, 0xEA, 0x35, 
        0x80, 0x0A, 0xD2, 0x72, 0x41, 0xED, 0x36, 0x0D, 
        0xFD, 0xE6, 0xE8, 0xCA, 0x61, 0x4F, 0x12, 0x04, 
        0x7F, 0xD0, 0x8B, 0x76, 0xAC, 0x4D, 0x13, 0xC0, 
        0x56, 0xA0, 0x69, 0x9E, 0x2F, 0x98, 0xA1, 0xCA, 
        0xC9, 0x10, 0x11, 0x29, 0x4D, 0x71, 0x20, 0x8F, 
        0x4A, 0xBA, 0xB3, 0x3B, 0xA8, 0x7A, 0xA0, 0x51, 
        0x7F, 0x41, 0x5B, 0xAC, 0xA8, 0x8D, 0x6B, 0xAC, 
        0x00, 0x60, 0x88, 0xFA, 0x60, 0x1D, 0x34, 0x94, 
        0x17, 0xE1, 0xF0, 0xC9, 0xB2, 0x3A, 0xFF, 0xA4, 
        0xD4, 0x96, 0x61, 0x8D, 0xBC, 0x02, 0x49, 0x86, 
        0xED, 0x69, 0x0B, 0xBB, 0x7B, 0x02, 0x57, 0x68, 
        0xFF, 0x9D, 0xF8, 0xAC, 0x15, 0x41, 0x6F, 0x48, 
        0x9F, 0x81, 0x29, 0xC3, 0x23, 0x41, 0xA8, 0xB4, 
        0x4F
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &key;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_PKCS1;
    kb.key_value = &kv;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_RSA;
    kb.cryptographic_length = 2048;
    
    struct private_key pk = {0};
    pk.key_block = &kb;
    
    int result = kmip_encode_private_key(&ctx, &pk);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_private_key(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[1280] = {
        0x42, 0x00, 0x64, 0x01, 0x00, 0x00, 0x04, 0xF8, 
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x04, 0xF0, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x04, 0xB8, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x04, 0xA9,
        0x30, 0x82, 0x04, 0xA5, 0x02, 0x01, 0x00, 0x02, 
        0x82, 0x01, 0x01, 0x00, 0xAB, 0x7F, 0x16, 0x1C, 
        0x00, 0x42, 0x49, 0x6C, 0xCD, 0x6C, 0x6D, 0x4D, 
        0xAD, 0xB9, 0x19, 0x97, 0x34, 0x35, 0x35, 0x77, 
        0x76, 0x00, 0x3A, 0xCF, 0x54, 0xB7, 0xAF, 0x1E, 
        0x44, 0x0A, 0xFB, 0x80, 0xB6, 0x4A, 0x87, 0x55, 
        0xF8, 0x00, 0x2C, 0xFE, 0xBA, 0x6B, 0x18, 0x45, 
        0x40, 0xA2, 0xD6, 0x60, 0x86, 0xD7, 0x46, 0x48, 
        0x34, 0x6D, 0x75, 0xB8, 0xD7, 0x18, 0x12, 0xB2, 
        0x05, 0x38, 0x7C, 0x0F, 0x65, 0x83, 0xBC, 0x4D, 
        0x7D, 0xC7, 0xEC, 0x11, 0x4F, 0x3B, 0x17, 0x6B, 
        0x79, 0x57, 0xC4, 0x22, 0xE7, 0xD0, 0x3F, 0xC6,
        0x26, 0x7F, 0xA2, 0xA6, 0xF8, 0x9B, 0x9B, 0xEE, 
        0x9E, 0x60, 0xA1, 0xD7, 0xC2, 0xD8, 0x33, 0xE5, 
        0xA5, 0xF4, 0xBB, 0x0B, 0x14, 0x34, 0xF4, 0xE7, 
        0x95, 0xA4, 0x11, 0x00, 0xF8, 0xAA, 0x21, 0x49, 
        0x00, 0xDF, 0x8B, 0x65, 0x08, 0x9F, 0x98, 0x13, 
        0x5B, 0x1C, 0x67, 0xB7, 0x01, 0x67, 0x5A, 0xBD, 
        0xBC, 0x7D, 0x57, 0x21, 0xAA, 0xC9, 0xD1, 0x4A, 
        0x7F, 0x08, 0x1F, 0xCE, 0xC8, 0x0B, 0x64, 0xE8, 
        0xA0, 0xEC, 0xC8, 0x29, 0x53, 0x53, 0xC7, 0x95, 
        0x32, 0x8A, 0xBF, 0x70, 0xE1, 0xB4, 0x2E, 0x7B, 
        0xB8, 0xB7, 0xF4, 0xE8, 0xAC, 0x8C, 0x81, 0x0C, 
        0xDB, 0x66, 0xE3, 0xD2, 0x11, 0x26, 0xEB, 0xA8, 
        0xDA, 0x7D, 0x0C, 0xA3, 0x41, 0x42, 0xCB, 0x76, 
        0xF9, 0x1F, 0x01, 0x3D, 0xA8, 0x09, 0xE9, 0xC1, 
        0xB7, 0xAE, 0x64, 0xC5, 0x41, 0x30, 0xFB, 0xC2, 
        0x1D, 0x80, 0xE9, 0xC2, 0xCB, 0x06, 0xC5, 0xC8, 
        0xD7, 0xCC, 0xE8, 0x94, 0x6A, 0x9A, 0xC9, 0x9B,
        0x1C, 0x28, 0x15, 0xC3, 0x61, 0x2A, 0x29, 0xA8, 
        0x2D, 0x73, 0xA1, 0xF9, 0x93, 0x74, 0xFE, 0x30, 
        0xE5, 0x49, 0x51, 0x66, 0x2A, 0x6E, 0xDA, 0x29, 
        0xC6, 0xFC, 0x41, 0x13, 0x35, 0xD5, 0xDC, 0x74, 
        0x26, 0xB0, 0xF6, 0x05, 0x02, 0x03, 0x01, 0x00, 
        0x01, 0x02, 0x82, 0x01, 0x00, 0x3B, 0x12, 0x45, 
        0x5D, 0x53, 0xC1, 0x81, 0x65, 0x16, 0xC5, 0x18, 
        0x49, 0x3F, 0x63, 0x98, 0xAA, 0xFA, 0x72, 0xB1, 
        0x7D, 0xFA, 0x89, 0x4D, 0xB8, 0x88, 0xA7, 0xD4, 
        0x8C, 0x0A, 0x47, 0xF6, 0x25, 0x79, 0xA4, 0xE6, 
        0x44, 0xF8, 0x6D, 0xA7, 0x11, 0xFE, 0xC8, 0x50, 
        0xCD, 0xD9, 0xDB, 0xBD, 0x17, 0xF6, 0x9A, 0x44, 
        0x3D, 0x2E, 0xC1, 0xDD, 0x60, 0xD3, 0xC6, 0x18, 
        0xFA, 0x74, 0xCD, 0xE5, 0xFD, 0xAF, 0xAB, 0xD6, 
        0xBA, 0xA2, 0x6E, 0xB0, 0xA3, 0xAD, 0xB4, 0xDE, 
        0xF6, 0x48, 0x0F, 0xB1, 0x21, 0x8C, 0xD3, 0xB0,
        0x83, 0xE2, 0x52, 0xE8, 0x85, 0xB6, 0xF0, 0x72, 
        0x9F, 0x98, 0xB2, 0x14, 0x4D, 0x2B, 0x72, 0x29, 
        0x3E, 0x1B, 0x11, 0xD7, 0x33, 0x93, 0xBC, 0x41, 
        0xF7, 0x5B, 0x15, 0xEE, 0x3D, 0x75, 0x69, 0xB4, 
        0x99, 0x5E, 0xD1, 0xA1, 0x44, 0x25, 0xDA, 0x43, 
        0x19, 0xB7, 0xB2, 0x6B, 0x0E, 0x8F, 0xEF, 0x17, 
        0xC3, 0x75, 0x42, 0xAE, 0x5C, 0x6D, 0x58, 0x49, 
        0xF8, 0x72, 0x09, 0x56, 0x7F, 0x39, 0x25, 0xA4, 
        0x7B, 0x01, 0x6D, 0x56, 0x48, 0x59, 0x71, 0x7B, 
        0xC5, 0x7F, 0xCB, 0x45, 0x22, 0xD0, 0xAA, 0x49, 
        0xCE, 0x81, 0x6E, 0x5B, 0xE7, 0xB3, 0x08, 0x81, 
        0x93, 0x23, 0x6E, 0xC9, 0xEF, 0xFF, 0x14, 0x08, 
        0x58, 0x04, 0x5B, 0x73, 0xC5, 0xD7, 0x9B, 0xAF, 
        0x38, 0xF7, 0xC6, 0x7F, 0x04, 0xC5, 0xDC, 0xF0, 
        0xE3, 0x80, 0x6A, 0xD9, 0x82, 0xD1, 0x25, 0x90, 
        0x58, 0xC3, 0x47, 0x3E, 0x84, 0x71, 0x79, 0xA8, 
        0x78, 0xF2, 0xC6, 0xB3, 0xBD, 0x96, 0x8F, 0xB9,
        0x9E, 0xA4, 0x6E, 0x91, 0x85, 0x89, 0x2F, 0x36,
        0x76, 0xE7, 0x89, 0x65, 0xC2, 0xAE, 0xD4, 0x87,
        0x7B, 0xA3, 0x91, 0x7D, 0xF0, 0x7C, 0x5E, 0x92, 
        0x74, 0x74, 0xF1, 0x9E, 0x76, 0x4B, 0xA6, 0x1D, 
        0xC3, 0x8D, 0x63, 0xBF, 0x29, 0x02, 0x81, 0x81, 
        0x00, 0xD5, 0xC6, 0x9C, 0x8C, 0x3C, 0xDC, 0x24, 
        0x64, 0x74, 0x4A, 0x79, 0x37, 0x13, 0xDA, 0xFB, 
        0x9F, 0x1D, 0xBC, 0x79, 0x9F, 0xF9, 0x64, 0x23, 
        0xFE, 0xCD, 0x3C, 0xBA, 0x79, 0x42, 0x86, 0xBC, 
        0xE9, 0x20, 0xF4, 0xB5, 0xC1, 0x83, 0xF9, 0x9E, 
        0xE9, 0x02, 0x8D, 0xB6, 0x21, 0x2C, 0x62, 0x77, 
        0xC4, 0xC8, 0x29, 0x7F, 0xCF, 0xBC, 0xE7, 0xF7,
        0xC2, 0x4C, 0xA4, 0xC5, 0x1F, 0xC7, 0x18, 0x2F, 
        0xB8, 0xF4, 0x01, 0x9F, 0xB1, 0xD5, 0x65, 0x96, 
        0x74, 0xC5, 0xCB, 0xE6, 0xD5, 0xFA, 0x99, 0x20, 
        0x51, 0x34, 0x17, 0x60, 0xCD, 0x00, 0x73, 0x57, 
        0x29, 0xA0, 0x70, 0xA9, 0xE5, 0x4D, 0x34, 0x2B, 
        0xEB, 0xA8, 0xEF, 0x47, 0xEE, 0x82, 0xD3, 0xA0, 
        0x1B, 0x04, 0xCE, 0xC4, 0xA0, 0x0D, 0x4D, 0xDB,
        0x41, 0xE3, 0x51, 0x16, 0xFC, 0x22, 0x1E, 0x85, 
        0x4B, 0x43, 0xA6, 0x96, 0xC0, 0xE6, 0x41, 0x9B, 
        0x1B, 0x02, 0x81, 0x81, 0x00, 0xCD, 0x5E, 0xA7, 
        0x70, 0x27, 0x89, 0x06, 0x4B, 0x67, 0x35, 0x40, 
        0xCB, 0xFF, 0x09, 0x35, 0x6A, 0xD8, 0x0B, 0xC3, 
        0xD5, 0x92, 0x81, 0x2E, 0xBA, 0x47, 0x61, 0x0B,
        0x9F, 0xAC, 0x6A, 0xEC, 0xEF, 0xE2, 0x2A, 0xCA, 
        0xE4, 0x38, 0x45, 0x9C, 0xDA, 0x74, 0xE5, 0x96, 
        0x53, 0xD8, 0x8C, 0x04, 0x18, 0x9D, 0x34, 0x39, 
        0x9B, 0xF5, 0xB1, 0x4B, 0x92, 0x0E, 0x34, 0xEF, 
        0x38, 0xA7, 0xD0, 0x9F, 0xE6, 0x95, 0x93, 0x39, 
        0x6E, 0x8F, 0xE7, 0x35, 0xE6, 0xF0, 0xA6, 0xAE, 
        0x49, 0x90, 0x40, 0x10, 0x41, 0xD8, 0xA4, 0x06, 
        0xB6, 0xFD, 0x86, 0xA1, 0x16, 0x1E, 0x45, 0xF9,
        0x5A, 0x3E, 0xAA, 0x5C, 0x10, 0x12, 0xE6, 0x66,
        0x2E, 0x44, 0xF1, 0x5F, 0x33, 0x5A, 0xC9, 0x71, 
        0xE1, 0x76, 0x6B, 0x2B, 0xB9, 0xC9, 0x85, 0x10, 
        0x99, 0x74, 0x14, 0x1B, 0x44, 0xD3, 0x7E, 0x1E, 
        0x31, 0x98, 0x20, 0xA5, 0x5F, 0x02, 0x81, 0x81, 
        0x00, 0xB2, 0x87, 0x12, 0x37, 0xBF, 0x9F, 0xAD, 
        0x38, 0xC3, 0x31, 0x6A, 0xB7, 0x87, 0x7A, 0x6A, 
        0x86, 0x80, 0x63, 0xE5, 0x42, 0xA7, 0x18, 0x6D, 
        0x43, 0x1E, 0x8D, 0x27, 0xC1, 0x9A, 0xC0, 0x41, 
        0x45, 0x84, 0x03, 0x39, 0x42, 0xE9, 0xFF, 0x6E, 
        0x29, 0x73, 0xBB, 0x7B, 0x2D, 0x8B, 0x0E, 0x94, 
        0xAD, 0x1E, 0xE8, 0x21, 0x58, 0x10, 0x8F, 0xBC,
        0x86, 0x64, 0x51, 0x7A, 0x5A, 0x46, 0x7F, 0xB9, 
        0x63, 0x01, 0x4B, 0xD5, 0xDC, 0xC2, 0xB4, 0xFB, 
        0x08, 0x7C, 0x23, 0x03, 0x9D, 0x11, 0x92, 0x0D, 
        0xBE, 0x22, 0xFD, 0x9F, 0x16, 0xB4, 0xD8, 0x9E, 
        0x23, 0x22, 0x5C, 0xD4, 0x55, 0xAD, 0xBA, 0xF3, 
        0x2E, 0xF4, 0x3F, 0x18, 0x58, 0x64, 0xA3, 0x6D,
        0x63, 0x03, 0x09, 0xD6, 0x85, 0x3F, 0x77, 0x14,
        0xB3, 0x9A, 0xAE, 0x1E, 0xBE, 0xE3, 0x93, 0x8F, 
        0x87, 0xC2, 0x70, 0x7E, 0x17, 0x8C, 0x73, 0x9F, 
        0x9F, 0x02, 0x81, 0x81, 0x00, 0x96, 0x90, 0xBE,
        0xD1, 0x4B, 0x2A, 0xFA, 0xA2, 0x6D, 0x98, 0x6D, 
        0x59, 0x22, 0x31, 0xEE, 0x27, 0xD7, 0x1D, 0x49, 
        0x06, 0x5B, 0xD2, 0xBA, 0x1F, 0x78, 0x15, 0x7E, 
        0x20, 0x22, 0x98, 0x81, 0xFD, 0x9D, 0x23, 0x22, 
        0x7D, 0x0F, 0x84, 0x79, 0xEA, 0xEF, 0xA9, 0x22, 
        0xFD, 0x75, 0xD5, 0xB1, 0x6B, 0x1A, 0x56, 0x1F,
        0xA6, 0x68, 0x0B, 0x04, 0x0C, 0xA0, 0xBD, 0xCE, 
        0x65, 0x0B, 0x23, 0xB9, 0x17, 0xA4, 0xB1, 0xBB, 
        0x79, 0x83, 0xA7, 0x4F, 0xAD, 0x70, 0xE1, 0xC3, 
        0x05, 0xCB, 0xEC, 0x2B, 0xFF, 0x1A, 0x85, 0xA7,
        0x26, 0xA1, 0xD9, 0x02, 0x60, 0xE4, 0xF1, 0x08, 
        0x4F, 0x51, 0x82, 0x34, 0xDC, 0xD3, 0xFE, 0x77, 
        0x0B, 0x95, 0x20, 0x21, 0x5B, 0xD5, 0x43, 0xBB, 
        0x6A, 0x41, 0x17, 0x71, 0x87, 0x54, 0x67, 0x6A, 
        0x34, 0x17, 0x16, 0x66, 0xA7, 0x9F, 0x26, 0xE7, 
        0x9C, 0x14, 0x9C, 0x5A, 0xA1, 0x02, 0x81, 0x81, 
        0x00, 0xA0, 0xC9, 0x85, 0xA0, 0xA0, 0xA7, 0x91, 
        0xA6, 0x59, 0xF9, 0x97, 0x31, 0x13, 0x4C, 0x44, 
        0xF3, 0x7B, 0x2E, 0x52, 0x0A, 0x2C, 0xEA, 0x35, 
        0x80, 0x0A, 0xD2, 0x72, 0x41, 0xED, 0x36, 0x0D, 
        0xFD, 0xE6, 0xE8, 0xCA, 0x61, 0x4F, 0x12, 0x04, 
        0x7F, 0xD0, 0x8B, 0x76, 0xAC, 0x4D, 0x13, 0xC0, 
        0x56, 0xA0, 0x69, 0x9E, 0x2F, 0x98, 0xA1, 0xCA, 
        0xC9, 0x10, 0x11, 0x29, 0x4D, 0x71, 0x20, 0x8F, 
        0x4A, 0xBA, 0xB3, 0x3B, 0xA8, 0x7A, 0xA0, 0x51, 
        0x7F, 0x41, 0x5B, 0xAC, 0xA8, 0x8D, 0x6B, 0xAC, 
        0x00, 0x60, 0x88, 0xFA, 0x60, 0x1D, 0x34, 0x94, 
        0x17, 0xE1, 0xF0, 0xC9, 0xB2, 0x3A, 0xFF, 0xA4, 
        0xD4, 0x96, 0x61, 0x8D, 0xBC, 0x02, 0x49, 0x86, 
        0xED, 0x69, 0x0B, 0xBB, 0x7B, 0x02, 0x57, 0x68, 
        0xFF, 0x9D, 0xF8, 0xAC, 0x15, 0x41, 0x6F, 0x48, 
        0x9F, 0x81, 0x29, 0xC3, 0x23, 0x41, 0xA8, 0xB4, 
        0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    uint8 value[1193] = {
        0x30, 0x82, 0x04, 0xA5, 0x02, 0x01, 0x00, 0x02, 
        0x82, 0x01, 0x01, 0x00, 0xAB, 0x7F, 0x16, 0x1C, 
        0x00, 0x42, 0x49, 0x6C, 0xCD, 0x6C, 0x6D, 0x4D, 
        0xAD, 0xB9, 0x19, 0x97, 0x34, 0x35, 0x35, 0x77, 
        0x76, 0x00, 0x3A, 0xCF, 0x54, 0xB7, 0xAF, 0x1E, 
        0x44, 0x0A, 0xFB, 0x80, 0xB6, 0x4A, 0x87, 0x55, 
        0xF8, 0x00, 0x2C, 0xFE, 0xBA, 0x6B, 0x18, 0x45, 
        0x40, 0xA2, 0xD6, 0x60, 0x86, 0xD7, 0x46, 0x48, 
        0x34, 0x6D, 0x75, 0xB8, 0xD7, 0x18, 0x12, 0xB2, 
        0x05, 0x38, 0x7C, 0x0F, 0x65, 0x83, 0xBC, 0x4D, 
        0x7D, 0xC7, 0xEC, 0x11, 0x4F, 0x3B, 0x17, 0x6B, 
        0x79, 0x57, 0xC4, 0x22, 0xE7, 0xD0, 0x3F, 0xC6,
        0x26, 0x7F, 0xA2, 0xA6, 0xF8, 0x9B, 0x9B, 0xEE, 
        0x9E, 0x60, 0xA1, 0xD7, 0xC2, 0xD8, 0x33, 0xE5, 
        0xA5, 0xF4, 0xBB, 0x0B, 0x14, 0x34, 0xF4, 0xE7, 
        0x95, 0xA4, 0x11, 0x00, 0xF8, 0xAA, 0x21, 0x49, 
        0x00, 0xDF, 0x8B, 0x65, 0x08, 0x9F, 0x98, 0x13, 
        0x5B, 0x1C, 0x67, 0xB7, 0x01, 0x67, 0x5A, 0xBD, 
        0xBC, 0x7D, 0x57, 0x21, 0xAA, 0xC9, 0xD1, 0x4A, 
        0x7F, 0x08, 0x1F, 0xCE, 0xC8, 0x0B, 0x64, 0xE8, 
        0xA0, 0xEC, 0xC8, 0x29, 0x53, 0x53, 0xC7, 0x95, 
        0x32, 0x8A, 0xBF, 0x70, 0xE1, 0xB4, 0x2E, 0x7B, 
        0xB8, 0xB7, 0xF4, 0xE8, 0xAC, 0x8C, 0x81, 0x0C, 
        0xDB, 0x66, 0xE3, 0xD2, 0x11, 0x26, 0xEB, 0xA8, 
        0xDA, 0x7D, 0x0C, 0xA3, 0x41, 0x42, 0xCB, 0x76, 
        0xF9, 0x1F, 0x01, 0x3D, 0xA8, 0x09, 0xE9, 0xC1, 
        0xB7, 0xAE, 0x64, 0xC5, 0x41, 0x30, 0xFB, 0xC2, 
        0x1D, 0x80, 0xE9, 0xC2, 0xCB, 0x06, 0xC5, 0xC8, 
        0xD7, 0xCC, 0xE8, 0x94, 0x6A, 0x9A, 0xC9, 0x9B,
        0x1C, 0x28, 0x15, 0xC3, 0x61, 0x2A, 0x29, 0xA8, 
        0x2D, 0x73, 0xA1, 0xF9, 0x93, 0x74, 0xFE, 0x30, 
        0xE5, 0x49, 0x51, 0x66, 0x2A, 0x6E, 0xDA, 0x29, 
        0xC6, 0xFC, 0x41, 0x13, 0x35, 0xD5, 0xDC, 0x74, 
        0x26, 0xB0, 0xF6, 0x05, 0x02, 0x03, 0x01, 0x00, 
        0x01, 0x02, 0x82, 0x01, 0x00, 0x3B, 0x12, 0x45, 
        0x5D, 0x53, 0xC1, 0x81, 0x65, 0x16, 0xC5, 0x18, 
        0x49, 0x3F, 0x63, 0x98, 0xAA, 0xFA, 0x72, 0xB1, 
        0x7D, 0xFA, 0x89, 0x4D, 0xB8, 0x88, 0xA7, 0xD4, 
        0x8C, 0x0A, 0x47, 0xF6, 0x25, 0x79, 0xA4, 0xE6, 
        0x44, 0xF8, 0x6D, 0xA7, 0x11, 0xFE, 0xC8, 0x50, 
        0xCD, 0xD9, 0xDB, 0xBD, 0x17, 0xF6, 0x9A, 0x44, 
        0x3D, 0x2E, 0xC1, 0xDD, 0x60, 0xD3, 0xC6, 0x18, 
        0xFA, 0x74, 0xCD, 0xE5, 0xFD, 0xAF, 0xAB, 0xD6, 
        0xBA, 0xA2, 0x6E, 0xB0, 0xA3, 0xAD, 0xB4, 0xDE, 
        0xF6, 0x48, 0x0F, 0xB1, 0x21, 0x8C, 0xD3, 0xB0,
        0x83, 0xE2, 0x52, 0xE8, 0x85, 0xB6, 0xF0, 0x72, 
        0x9F, 0x98, 0xB2, 0x14, 0x4D, 0x2B, 0x72, 0x29, 
        0x3E, 0x1B, 0x11, 0xD7, 0x33, 0x93, 0xBC, 0x41, 
        0xF7, 0x5B, 0x15, 0xEE, 0x3D, 0x75, 0x69, 0xB4, 
        0x99, 0x5E, 0xD1, 0xA1, 0x44, 0x25, 0xDA, 0x43, 
        0x19, 0xB7, 0xB2, 0x6B, 0x0E, 0x8F, 0xEF, 0x17, 
        0xC3, 0x75, 0x42, 0xAE, 0x5C, 0x6D, 0x58, 0x49, 
        0xF8, 0x72, 0x09, 0x56, 0x7F, 0x39, 0x25, 0xA4, 
        0x7B, 0x01, 0x6D, 0x56, 0x48, 0x59, 0x71, 0x7B, 
        0xC5, 0x7F, 0xCB, 0x45, 0x22, 0xD0, 0xAA, 0x49, 
        0xCE, 0x81, 0x6E, 0x5B, 0xE7, 0xB3, 0x08, 0x81, 
        0x93, 0x23, 0x6E, 0xC9, 0xEF, 0xFF, 0x14, 0x08, 
        0x58, 0x04, 0x5B, 0x73, 0xC5, 0xD7, 0x9B, 0xAF, 
        0x38, 0xF7, 0xC6, 0x7F, 0x04, 0xC5, 0xDC, 0xF0, 
        0xE3, 0x80, 0x6A, 0xD9, 0x82, 0xD1, 0x25, 0x90, 
        0x58, 0xC3, 0x47, 0x3E, 0x84, 0x71, 0x79, 0xA8, 
        0x78, 0xF2, 0xC6, 0xB3, 0xBD, 0x96, 0x8F, 0xB9,
        0x9E, 0xA4, 0x6E, 0x91, 0x85, 0x89, 0x2F, 0x36,
        0x76, 0xE7, 0x89, 0x65, 0xC2, 0xAE, 0xD4, 0x87,
        0x7B, 0xA3, 0x91, 0x7D, 0xF0, 0x7C, 0x5E, 0x92, 
        0x74, 0x74, 0xF1, 0x9E, 0x76, 0x4B, 0xA6, 0x1D, 
        0xC3, 0x8D, 0x63, 0xBF, 0x29, 0x02, 0x81, 0x81, 
        0x00, 0xD5, 0xC6, 0x9C, 0x8C, 0x3C, 0xDC, 0x24, 
        0x64, 0x74, 0x4A, 0x79, 0x37, 0x13, 0xDA, 0xFB, 
        0x9F, 0x1D, 0xBC, 0x79, 0x9F, 0xF9, 0x64, 0x23, 
        0xFE, 0xCD, 0x3C, 0xBA, 0x79, 0x42, 0x86, 0xBC, 
        0xE9, 0x20, 0xF4, 0xB5, 0xC1, 0x83, 0xF9, 0x9E, 
        0xE9, 0x02, 0x8D, 0xB6, 0x21, 0x2C, 0x62, 0x77, 
        0xC4, 0xC8, 0x29, 0x7F, 0xCF, 0xBC, 0xE7, 0xF7,
        0xC2, 0x4C, 0xA4, 0xC5, 0x1F, 0xC7, 0x18, 0x2F, 
        0xB8, 0xF4, 0x01, 0x9F, 0xB1, 0xD5, 0x65, 0x96, 
        0x74, 0xC5, 0xCB, 0xE6, 0xD5, 0xFA, 0x99, 0x20, 
        0x51, 0x34, 0x17, 0x60, 0xCD, 0x00, 0x73, 0x57, 
        0x29, 0xA0, 0x70, 0xA9, 0xE5, 0x4D, 0x34, 0x2B, 
        0xEB, 0xA8, 0xEF, 0x47, 0xEE, 0x82, 0xD3, 0xA0, 
        0x1B, 0x04, 0xCE, 0xC4, 0xA0, 0x0D, 0x4D, 0xDB,
        0x41, 0xE3, 0x51, 0x16, 0xFC, 0x22, 0x1E, 0x85, 
        0x4B, 0x43, 0xA6, 0x96, 0xC0, 0xE6, 0x41, 0x9B, 
        0x1B, 0x02, 0x81, 0x81, 0x00, 0xCD, 0x5E, 0xA7, 
        0x70, 0x27, 0x89, 0x06, 0x4B, 0x67, 0x35, 0x40, 
        0xCB, 0xFF, 0x09, 0x35, 0x6A, 0xD8, 0x0B, 0xC3, 
        0xD5, 0x92, 0x81, 0x2E, 0xBA, 0x47, 0x61, 0x0B,
        0x9F, 0xAC, 0x6A, 0xEC, 0xEF, 0xE2, 0x2A, 0xCA, 
        0xE4, 0x38, 0x45, 0x9C, 0xDA, 0x74, 0xE5, 0x96, 
        0x53, 0xD8, 0x8C, 0x04, 0x18, 0x9D, 0x34, 0x39, 
        0x9B, 0xF5, 0xB1, 0x4B, 0x92, 0x0E, 0x34, 0xEF, 
        0x38, 0xA7, 0xD0, 0x9F, 0xE6, 0x95, 0x93, 0x39, 
        0x6E, 0x8F, 0xE7, 0x35, 0xE6, 0xF0, 0xA6, 0xAE, 
        0x49, 0x90, 0x40, 0x10, 0x41, 0xD8, 0xA4, 0x06, 
        0xB6, 0xFD, 0x86, 0xA1, 0x16, 0x1E, 0x45, 0xF9,
        0x5A, 0x3E, 0xAA, 0x5C, 0x10, 0x12, 0xE6, 0x66,
        0x2E, 0x44, 0xF1, 0x5F, 0x33, 0x5A, 0xC9, 0x71, 
        0xE1, 0x76, 0x6B, 0x2B, 0xB9, 0xC9, 0x85, 0x10, 
        0x99, 0x74, 0x14, 0x1B, 0x44, 0xD3, 0x7E, 0x1E, 
        0x31, 0x98, 0x20, 0xA5, 0x5F, 0x02, 0x81, 0x81, 
        0x00, 0xB2, 0x87, 0x12, 0x37, 0xBF, 0x9F, 0xAD, 
        0x38, 0xC3, 0x31, 0x6A, 0xB7, 0x87, 0x7A, 0x6A, 
        0x86, 0x80, 0x63, 0xE5, 0x42, 0xA7, 0x18, 0x6D, 
        0x43, 0x1E, 0x8D, 0x27, 0xC1, 0x9A, 0xC0, 0x41, 
        0x45, 0x84, 0x03, 0x39, 0x42, 0xE9, 0xFF, 0x6E, 
        0x29, 0x73, 0xBB, 0x7B, 0x2D, 0x8B, 0x0E, 0x94, 
        0xAD, 0x1E, 0xE8, 0x21, 0x58, 0x10, 0x8F, 0xBC,
        0x86, 0x64, 0x51, 0x7A, 0x5A, 0x46, 0x7F, 0xB9, 
        0x63, 0x01, 0x4B, 0xD5, 0xDC, 0xC2, 0xB4, 0xFB, 
        0x08, 0x7C, 0x23, 0x03, 0x9D, 0x11, 0x92, 0x0D, 
        0xBE, 0x22, 0xFD, 0x9F, 0x16, 0xB4, 0xD8, 0x9E, 
        0x23, 0x22, 0x5C, 0xD4, 0x55, 0xAD, 0xBA, 0xF3, 
        0x2E, 0xF4, 0x3F, 0x18, 0x58, 0x64, 0xA3, 0x6D,
        0x63, 0x03, 0x09, 0xD6, 0x85, 0x3F, 0x77, 0x14,
        0xB3, 0x9A, 0xAE, 0x1E, 0xBE, 0xE3, 0x93, 0x8F, 
        0x87, 0xC2, 0x70, 0x7E, 0x17, 0x8C, 0x73, 0x9F, 
        0x9F, 0x02, 0x81, 0x81, 0x00, 0x96, 0x90, 0xBE,
        0xD1, 0x4B, 0x2A, 0xFA, 0xA2, 0x6D, 0x98, 0x6D, 
        0x59, 0x22, 0x31, 0xEE, 0x27, 0xD7, 0x1D, 0x49, 
        0x06, 0x5B, 0xD2, 0xBA, 0x1F, 0x78, 0x15, 0x7E, 
        0x20, 0x22, 0x98, 0x81, 0xFD, 0x9D, 0x23, 0x22, 
        0x7D, 0x0F, 0x84, 0x79, 0xEA, 0xEF, 0xA9, 0x22, 
        0xFD, 0x75, 0xD5, 0xB1, 0x6B, 0x1A, 0x56, 0x1F,
        0xA6, 0x68, 0x0B, 0x04, 0x0C, 0xA0, 0xBD, 0xCE, 
        0x65, 0x0B, 0x23, 0xB9, 0x17, 0xA4, 0xB1, 0xBB, 
        0x79, 0x83, 0xA7, 0x4F, 0xAD, 0x70, 0xE1, 0xC3, 
        0x05, 0xCB, 0xEC, 0x2B, 0xFF, 0x1A, 0x85, 0xA7,
        0x26, 0xA1, 0xD9, 0x02, 0x60, 0xE4, 0xF1, 0x08, 
        0x4F, 0x51, 0x82, 0x34, 0xDC, 0xD3, 0xFE, 0x77, 
        0x0B, 0x95, 0x20, 0x21, 0x5B, 0xD5, 0x43, 0xBB, 
        0x6A, 0x41, 0x17, 0x71, 0x87, 0x54, 0x67, 0x6A, 
        0x34, 0x17, 0x16, 0x66, 0xA7, 0x9F, 0x26, 0xE7, 
        0x9C, 0x14, 0x9C, 0x5A, 0xA1, 0x02, 0x81, 0x81, 
        0x00, 0xA0, 0xC9, 0x85, 0xA0, 0xA0, 0xA7, 0x91, 
        0xA6, 0x59, 0xF9, 0x97, 0x31, 0x13, 0x4C, 0x44, 
        0xF3, 0x7B, 0x2E, 0x52, 0x0A, 0x2C, 0xEA, 0x35, 
        0x80, 0x0A, 0xD2, 0x72, 0x41, 0xED, 0x36, 0x0D, 
        0xFD, 0xE6, 0xE8, 0xCA, 0x61, 0x4F, 0x12, 0x04, 
        0x7F, 0xD0, 0x8B, 0x76, 0xAC, 0x4D, 0x13, 0xC0, 
        0x56, 0xA0, 0x69, 0x9E, 0x2F, 0x98, 0xA1, 0xCA, 
        0xC9, 0x10, 0x11, 0x29, 0x4D, 0x71, 0x20, 0x8F, 
        0x4A, 0xBA, 0xB3, 0x3B, 0xA8, 0x7A, 0xA0, 0x51, 
        0x7F, 0x41, 0x5B, 0xAC, 0xA8, 0x8D, 0x6B, 0xAC, 
        0x00, 0x60, 0x88, 0xFA, 0x60, 0x1D, 0x34, 0x94, 
        0x17, 0xE1, 0xF0, 0xC9, 0xB2, 0x3A, 0xFF, 0xA4, 
        0xD4, 0x96, 0x61, 0x8D, 0xBC, 0x02, 0x49, 0x86, 
        0xED, 0x69, 0x0B, 0xBB, 0x7B, 0x02, 0x57, 0x68, 
        0xFF, 0x9D, 0xF8, 0xAC, 0x15, 0x41, 0x6F, 0x48, 
        0x9F, 0x81, 0x29, 0xC3, 0x23, 0x41, 0xA8, 0xB4, 
        0x4F
    };
    struct byte_string key = {0};
    key.value = value;
    key.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &key;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_PKCS1;
    kb.key_value = &kv;
    kb.key_value_type = KMIP_TYPE_STRUCTURE;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_RSA;
    kb.cryptographic_length = 2048;
    
    struct private_key expected = {0};
    expected.key_block = &kb;
    
    struct private_key observed = {0};
    
    int result = kmip_decode_private_key(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_private_key(&expected, &observed),
        result,
        __func__);
    kmip_free_private_key(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_key_wrapping_specification(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[136] = {
        0x42, 0x00, 0x47, 0x01, 0x00, 0x00, 0x00, 0x80, 
        0x42, 0x00, 0x9E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x36, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x66, 0x34, 0x62, 0x32, 0x62, 0x34, 0x63, 0x33, 
        0x2D, 0x34, 0x63, 0x31, 0x39, 0x2D, 0x34, 0x65, 
        0x63, 0x66, 0x2D, 0x38, 0x32, 0x37, 0x61, 0x2D, 
        0x30, 0x31, 0x31, 0x63, 0x61, 0x36, 0x30, 0x35, 
        0x37, 0x64, 0x33, 0x65, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10, 
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x55, 0x73, 
        0x61, 0x67, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x6B
    };
    
    uint8 observed[136] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "f4b2b4c3-4c19-4ecf-827a-011ca6057d3e";
    uuid.size = 36;
    
    struct cryptographic_parameters cp = {0};
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;
    
    struct encryption_key_information eki = {0};
    eki.unique_identifier = &uuid;
    eki.cryptographic_parameters = &cp;
    
    struct text_string attribute_name = {0};
    attribute_name.value = "Cryptographic Usage Mask";
    attribute_name.size = 24;
    
    struct key_wrapping_specification kws = {0};
    kws.wrapping_method = KMIP_WRAP_ENCRYPT;
    kws.encryption_key_info = &eki;
    kws.attribute_names = &attribute_name;
    kws.attribute_name_count = 1;
    
    int result = kmip_encode_key_wrapping_specification(&ctx, &kws);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_key_wrapping_specification(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[136] = {
        0x42, 0x00, 0x47, 0x01, 0x00, 0x00, 0x00, 0x80, 
        0x42, 0x00, 0x9E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x36, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x66, 0x34, 0x62, 0x32, 0x62, 0x34, 0x63, 0x33, 
        0x2D, 0x34, 0x63, 0x31, 0x39, 0x2D, 0x34, 0x65, 
        0x63, 0x66, 0x2D, 0x38, 0x32, 0x37, 0x61, 0x2D, 
        0x30, 0x31, 0x31, 0x63, 0x61, 0x36, 0x30, 0x35, 
        0x37, 0x64, 0x33, 0x65, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10, 
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x55, 0x73, 
        0x61, 0x67, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x6B
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "f4b2b4c3-4c19-4ecf-827a-011ca6057d3e";
    uuid.size = 36;
    
    struct cryptographic_parameters cp = {0};
    kmip_init_cryptographic_parameters(&cp);
    
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;
    
    struct encryption_key_information eki = {0};
    eki.unique_identifier = &uuid;
    eki.cryptographic_parameters = &cp;
    
    struct text_string attribute_name = {0};
    attribute_name.value = "Cryptographic Usage Mask";
    attribute_name.size = 24;
    
    struct key_wrapping_specification expected = {0};
    expected.wrapping_method = KMIP_WRAP_ENCRYPT;
    expected.encryption_key_info = &eki;
    expected.attribute_names = &attribute_name;
    expected.attribute_name_count = 1;
    
    struct key_wrapping_specification observed = {0};
    
    int result = kmip_decode_key_wrapping_specification(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_key_wrapping_specification(&expected, &observed),
        result,
        __func__);
    kmip_free_key_wrapping_specification(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_create_request_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following set of values:
    *  Request Payload
    *      Object Type - Symmetric Key
    *      Template Attribute
    *          Attribute
    *              Attribute Name - Cryptographic Algorithm
    *              Attribute Value - AES
    *          Attribute
    *              Attribute Name - Cryptographic Length
    *              Attribute Value - 128
    *          Attribute
    *              Attribute Name - Cryptographic Usage Mask
    *              Attribute Value - Encrypt | Decrypt
    */
    uint8 expected[200] = {
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0xC0, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x91, 0x01, 0x00, 0x00, 0x00, 0xA8, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x17, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x6C, 
        0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x14, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x4C, 0x65, 
        0x6E, 0x67, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x55, 0x73, 
        0x61, 0x67, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x6B, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[200] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct attribute a[3] = {{0}};
    for(int i = 0; i < 3; i++)
    {
        kmip_init_attribute(&a[i]);
    }
    
    enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES;
    a[0].type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    a[0].value = &algorithm;
    
    int32 length = 128;
    a[1].type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    a[1].value = &length;
    
    int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT;
    a[2].type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK;
    a[2].value = &mask;
    
    struct template_attribute ta = {0};
    ta.attributes = a;
    ta.attribute_count = ARRAY_LENGTH(a);
    
    struct create_request_payload crp = {0};
    crp.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    crp.template_attribute = &ta;
    
    int result = kmip_encode_create_request_payload(&ctx, &crp);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_create_request_payload_kmip_2_0(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following set of values:
    *  Request Payload
    *      Object Type - Symmetric Key
    *      Attributes
    *          Cryptographic Algorithm - AES
    *          Cryptographic Length - 128
    *          Cryptographic Usage Mask - Encrypt | Decrypt
    *      Protection Storage Masks
    *          Protection Storage Mask - Software | On System
    *          Protection Storage Mask - Off System | Off Premises
    */
    uint8 expected[120] = {
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x70, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x25, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2C, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x5F, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x01, 0x5E, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x5E, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[120] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_2_0);
    
    Attribute a[3] = {{0}};
    for(int i = 0; i < 3; i++)
    {
        kmip_init_attribute(&a[i]);
    }
    
    enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES;
    a[0].type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    a[0].value = &algorithm;
    
    int32 length = 128;
    a[1].type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    a[1].value = &length;
    
    int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT;
    a[2].type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK;
    a[2].value = &mask;
    
    Attributes attributes = {0};
    LinkedList list = {0};
    LinkedListItem item_1, item_2, item_3 = {0};
    item_1.data = &a[0];
    item_2.data = &a[1];
    item_3.data = &a[2];
    kmip_linked_list_enqueue(&list, &item_1);
    kmip_linked_list_enqueue(&list, &item_2);
    kmip_linked_list_enqueue(&list, &item_3);
    attributes.attribute_list = &list;

    ProtectionStorageMasks psm = {0};
    LinkedList masks = {0};
    LinkedListItem mask_1, mask_2 = {0};
    int32 m1 = KMIP_PROTECT_SOFTWARE | KMIP_PROTECT_ON_SYSTEM;
    int32 m2 = KMIP_PROTECT_OFF_SYSTEM | KMIP_PROTECT_OFF_PREMISES;
    mask_1.data = &m1;
    mask_2.data = &m2;
    kmip_linked_list_enqueue(&masks, &mask_1);
    kmip_linked_list_enqueue(&masks, &mask_2);
    psm.masks = &masks;

    CreateRequestPayload payload = {0};
    payload.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    payload.attributes = &attributes;
    payload.protection_storage_masks = &psm;
    
    int result = kmip_encode_create_request_payload(&ctx, &payload);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_create_request_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[200] = {
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0xC0, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x91, 0x01, 0x00, 0x00, 0x00, 0xA8, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x17, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x6C, 
        0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x14, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x4C, 0x65, 
        0x6E, 0x67, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x55, 0x73, 
        0x61, 0x67, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x6B, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct attribute a[3] = {{0}};
    for(int i = 0; i < 3; i++)
    {
        kmip_init_attribute(&a[i]);
    }
    
    enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES;
    a[0].type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    a[0].value = &algorithm;
    
    int32 length = 128;
    a[1].type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    a[1].value = &length;
    
    int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT;
    a[2].type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK;
    a[2].value = &mask;
    
    struct template_attribute ta = {0};
    ta.attributes = a;
    ta.attribute_count = ARRAY_LENGTH(a);
    
    struct create_request_payload expected = {0};
    expected.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    expected.template_attribute = &ta;
    
    struct create_request_payload observed = {0};
    
    int result = kmip_decode_create_request_payload(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_create_request_payload(&expected, &observed),
        result,
        __func__);
    kmip_free_create_request_payload(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_create_request_payload_kmip_2_0(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following set of values:
    *  Request Payload
    *      Object Type - Symmetric Key
    *      Attributes
    *          Cryptographic Algorithm - AES
    *          Cryptographic Length - 128
    *          Cryptographic Usage Mask - Encrypt | Decrypt
    *      Protection Storage Masks
    *          Protection Storage Mask - Software | On System
    *          Protection Storage Mask - Off System | Off Premises
    */
    uint8 encoding[120] = {
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x70, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x25, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2C, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x5F, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x01, 0x5E, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x5E, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);
    
    Attribute a[3] = {{0}};
    for(int i = 0; i < 3; i++)
    {
        kmip_init_attribute(&a[i]);
    }
    
    enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES;
    a[0].type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    a[0].value = &algorithm;
    
    int32 length = 128;
    a[1].type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    a[1].value = &length;
    
    int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT;
    a[2].type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK;
    a[2].value = &mask;
    
    Attributes attributes = {0};
    LinkedList list = {0};
    LinkedListItem item_1, item_2, item_3 = {0};
    item_1.data = &a[0];
    item_2.data = &a[1];
    item_3.data = &a[2];
    kmip_linked_list_enqueue(&list, &item_1);
    kmip_linked_list_enqueue(&list, &item_2);
    kmip_linked_list_enqueue(&list, &item_3);
    attributes.attribute_list = &list;

    ProtectionStorageMasks psm = {0};
    LinkedList masks = {0};
    LinkedListItem mask_1, mask_2 = {0};
    int32 m1 = KMIP_PROTECT_SOFTWARE | KMIP_PROTECT_ON_SYSTEM;
    int32 m2 = KMIP_PROTECT_OFF_SYSTEM | KMIP_PROTECT_OFF_PREMISES;
    mask_1.data = &m1;
    mask_2.data = &m2;
    kmip_linked_list_enqueue(&masks, &mask_1);
    kmip_linked_list_enqueue(&masks, &mask_2);
    psm.masks = &masks;

    CreateRequestPayload expected = {0};
    expected.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    expected.attributes = &attributes;
    expected.protection_storage_masks = &psm;
    
    CreateRequestPayload observed = {0};
    
    int result = kmip_decode_create_request_payload(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_create_request_payload(&expected, &observed),
        result,
        __func__);
    kmip_free_create_request_payload(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_create_response_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[72] = {
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x40, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x66, 0x62, 0x34, 0x62, 0x35, 0x62, 0x39, 0x63, 
        0x2D, 0x36, 0x31, 0x38, 0x38, 0x2D, 0x34, 0x63, 
        0x36, 0x33, 0x2D, 0x38, 0x31, 0x34, 0x32, 0x2D, 
        0x66, 0x65, 0x39, 0x63, 0x33, 0x32, 0x38, 0x31, 
        0x32, 0x39, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[72] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "fb4b5b9c-6188-4c63-8142-fe9c328129fc";
    uuid.size = 36;
    
    struct create_response_payload crp = {0};
    crp.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    crp.unique_identifier = &uuid;
    
    int result = kmip_encode_create_response_payload(&ctx, &crp);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_create_response_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[72] = {
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x40, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x66, 0x62, 0x34, 0x62, 0x35, 0x62, 0x39, 0x63, 
        0x2D, 0x36, 0x31, 0x38, 0x38, 0x2D, 0x34, 0x63, 
        0x36, 0x33, 0x2D, 0x38, 0x31, 0x34, 0x32, 0x2D, 
        0x66, 0x65, 0x39, 0x63, 0x33, 0x32, 0x38, 0x31, 
        0x32, 0x39, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "fb4b5b9c-6188-4c63-8142-fe9c328129fc";
    uuid.size = 36;
    
    struct create_response_payload expected = {0};
    expected.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    expected.unique_identifier = &uuid;
    
    struct create_response_payload observed = {0};
    
    int result = kmip_decode_create_response_payload(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_create_response_payload(&expected, &observed),
        result,
        __func__);
    kmip_free_create_response_payload(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_create_response_payload_with_template_attribute(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[136] = {
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x80, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x66, 0x62, 0x34, 0x62, 0x35, 0x62, 0x39, 0x63, 
        0x2D, 0x36, 0x31, 0x38, 0x38, 0x2D, 0x34, 0x63, 
        0x36, 0x33, 0x2D, 0x38, 0x31, 0x34, 0x32, 0x2D, 
        0x66, 0x65, 0x39, 0x63, 0x33, 0x32, 0x38, 0x31, 
        0x32, 0x39, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x91, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x17, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x6C, 
        0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
    };
    
    uint8 observed[136] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "fb4b5b9c-6188-4c63-8142-fe9c328129fc";
    uuid.size = 36;
    
    struct attribute a = {0};
    kmip_init_attribute(&a);
    
    enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES;
    a.type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    a.value = &algorithm;
    
    struct template_attribute ta = {0};
    ta.attributes = &a;
    ta.attribute_count = 1;
    
    struct create_response_payload crp = {0};
    crp.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    crp.unique_identifier = &uuid;
    crp.template_attribute = &ta;
    
    int result = kmip_encode_create_response_payload(&ctx, &crp);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_create_response_payload_with_template_attribute(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[136] = {
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x80, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x66, 0x62, 0x34, 0x62, 0x35, 0x62, 0x39, 0x63, 
        0x2D, 0x36, 0x31, 0x38, 0x38, 0x2D, 0x34, 0x63, 
        0x36, 0x33, 0x2D, 0x38, 0x31, 0x34, 0x32, 0x2D, 
        0x66, 0x65, 0x39, 0x63, 0x33, 0x32, 0x38, 0x31, 
        0x32, 0x39, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x91, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x17, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x6C, 
        0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "fb4b5b9c-6188-4c63-8142-fe9c328129fc";
    uuid.size = 36;
    
    struct attribute a = {0};
    kmip_init_attribute(&a);
    
    enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES;
    a.type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    a.value = &algorithm;
    
    struct template_attribute ta = {0};
    ta.attributes = &a;
    ta.attribute_count = 1;
    
    struct create_response_payload expected = {0};
    expected.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    expected.unique_identifier = &uuid;
    expected.template_attribute = &ta;
    
    struct create_response_payload observed = {0};
    
    int result = kmip_decode_create_response_payload(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_create_response_payload(&expected, &observed),
        result,
        __func__);
    kmip_free_create_response_payload(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_get_request_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[56] = {
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[56] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    struct get_request_payload grp = {0};
    grp.unique_identifier = &uuid;
    
    int result = kmip_encode_get_request_payload(&ctx, &grp);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_get_request_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[56] = {
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    struct get_request_payload expected = {0};
    expected.unique_identifier = &uuid;
    
    struct get_request_payload observed = {0};
    
    int result = kmip_decode_get_request_payload(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_get_request_payload(&expected, &observed),
        result,
        __func__);
    kmip_free_get_request_payload(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_get_request_payload_with_format_compression(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[88] = {
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x50, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x37, 0x63, 0x66, 0x35, 0x32, 0x30, 0x39, 0x62, 
        0x2D, 0x36, 0x66, 0x66, 0x36, 0x2D, 0x34, 0x34, 
        0x32, 0x36, 0x2D, 0x38, 0x39, 0x39, 0x65, 0x2D, 
        0x32, 0x32, 0x62, 0x30, 0x36, 0x37, 0x38, 0x35, 
        0x39, 0x33, 0x37, 0x32, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x41, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[88] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "7cf5209b-6ff6-4426-899e-22b067859372";
    uuid.size = 36;
    
    struct get_request_payload grp = {0};
    grp.unique_identifier = &uuid;
    grp.key_format_type = KMIP_KEYFORMAT_PKCS1;
    grp.key_compression_type = KMIP_KEYCOMP_EC_PUB_UNCOMPRESSED;
    
    int result = kmip_encode_get_request_payload(&ctx, &grp);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_get_request_payload_with_wrapping_spec(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[160] = {
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x98, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x62, 0x66, 0x66, 0x37, 0x33, 0x34, 0x37, 0x62, 
        0x2D, 0x33, 0x61, 0x33, 0x39, 0x2D, 0x34, 0x63, 
        0x63, 0x62, 0x2D, 0x38, 0x32, 0x33, 0x34, 0x2D, 
        0x62, 0x61, 0x32, 0x35, 0x36, 0x30, 0x63, 0x61, 
        0x31, 0x35, 0x39, 0x38, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x47, 0x01, 0x00, 0x00, 0x00, 0x60, 
        0x42, 0x00, 0x9E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x36, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35, 
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D, 
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10, 
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[160] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string wrapping_uuid = {0};
    wrapping_uuid.value = "100182d5-72b8-47aa-8383-4d97d512e98a";
    wrapping_uuid.size = 36;
    struct text_string uuid = {0};
    uuid.value = "bff7347b-3a39-4ccb-8234-ba2560ca1598";
    uuid.size = 36;
    
    struct cryptographic_parameters cp = {0};
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;
    
    struct encryption_key_information eki = {0};
    eki.unique_identifier = &wrapping_uuid;
    eki.cryptographic_parameters = &cp;
    
    struct key_wrapping_specification kws = {0};
    kws.wrapping_method = KMIP_WRAP_ENCRYPT;
    kws.encryption_key_info = &eki;
    
    struct get_request_payload grp = {0};
    grp.unique_identifier = &uuid;
    grp.key_wrapping_spec = &kws;
    
    int result = kmip_encode_get_request_payload(&ctx, &grp);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_get_response_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[176] = {
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0xA8, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x8F, 0x01, 0x00, 0x00, 0x00, 0x60, 
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x58, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x18, 
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[176] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    uint8 value[24] = {
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8
    };
    struct byte_string v = {0};
    v.value = value;
    v.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &v;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_RAW;
    kb.key_value = &kv;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_TRIPLE_DES;
    kb.cryptographic_length = 168;
    
    struct symmetric_key key = {0};
    key.key_block = &kb;
    
    struct get_response_payload grp = {0};
    grp.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    grp.unique_identifier = &uuid;
    grp.object = &key;
    
    int result = kmip_encode_get_response_payload(&ctx, &grp);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_get_response_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[176] = {
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0xA8, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x8F, 0x01, 0x00, 0x00, 0x00, 0x60, 
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x58, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x18, 
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    uint8 value[24] = {
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8
    };
    struct byte_string v = {0};
    v.value = value;
    v.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &v;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_RAW;
    kb.key_value = &kv;
    kb.key_value_type = KMIP_TYPE_STRUCTURE;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_TRIPLE_DES;
    kb.cryptographic_length = 168;
    
    struct symmetric_key key = {0};
    key.key_block = &kb;
    
    struct get_response_payload expected = {0};
    expected.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    expected.unique_identifier = &uuid;
    expected.object = &key;
    
    struct get_response_payload observed = {0};
    
    int result = kmip_decode_get_response_payload(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_get_response_payload(&expected, &observed),
        result,
        __func__);
    kmip_free_get_response_payload(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_destroy_request_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[56] = {
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x66, 0x62, 0x34, 0x62, 0x35, 0x62, 0x39, 0x63, 
        0x2D, 0x36, 0x31, 0x38, 0x38, 0x2D, 0x34, 0x63, 
        0x36, 0x33, 0x2D, 0x38, 0x31, 0x34, 0x32, 0x2D, 
        0x66, 0x65, 0x39, 0x63, 0x33, 0x32, 0x38, 0x31, 
        0x32, 0x39, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[56] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "fb4b5b9c-6188-4c63-8142-fe9c328129fc";
    uuid.size = 36;
    
    struct destroy_request_payload drp = {0};
    drp.unique_identifier = &uuid;
    
    int result = kmip_encode_destroy_request_payload(&ctx, &drp);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_destroy_request_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[56] = {
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x66, 0x62, 0x34, 0x62, 0x35, 0x62, 0x39, 0x63, 
        0x2D, 0x36, 0x31, 0x38, 0x38, 0x2D, 0x34, 0x63, 
        0x36, 0x33, 0x2D, 0x38, 0x31, 0x34, 0x32, 0x2D, 
        0x66, 0x65, 0x39, 0x63, 0x33, 0x32, 0x38, 0x31, 
        0x32, 0x39, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "fb4b5b9c-6188-4c63-8142-fe9c328129fc";
    uuid.size = 36;
    
    struct destroy_request_payload expected = {0};
    expected.unique_identifier = &uuid;
    
    struct destroy_request_payload observed = {0};
    
    int result = kmip_decode_destroy_request_payload(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_destroy_request_payload(&expected, &observed),
        result,
        __func__);
    kmip_free_destroy_request_payload(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_destroy_response_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[56] = {
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x66, 0x62, 0x34, 0x62, 0x35, 0x62, 0x39, 0x63, 
        0x2D, 0x36, 0x31, 0x38, 0x38, 0x2D, 0x34, 0x63, 
        0x36, 0x33, 0x2D, 0x38, 0x31, 0x34, 0x32, 0x2D, 
        0x66, 0x65, 0x39, 0x63, 0x33, 0x32, 0x38, 0x31, 
        0x32, 0x39, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[56] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "fb4b5b9c-6188-4c63-8142-fe9c328129fc";
    uuid.size = 36;
    
    struct destroy_response_payload drp = {0};
    drp.unique_identifier = &uuid;
    
    int result = kmip_encode_destroy_response_payload(&ctx, &drp);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_destroy_response_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[56] = {
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x66, 0x62, 0x34, 0x62, 0x35, 0x62, 0x39, 0x63, 
        0x2D, 0x36, 0x31, 0x38, 0x38, 0x2D, 0x34, 0x63, 
        0x36, 0x33, 0x2D, 0x38, 0x31, 0x34, 0x32, 0x2D, 
        0x66, 0x65, 0x39, 0x63, 0x33, 0x32, 0x38, 0x31, 
        0x32, 0x39, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "fb4b5b9c-6188-4c63-8142-fe9c328129fc";
    uuid.size = 36;
    
    struct destroy_response_payload expected = {0};
    expected.unique_identifier = &uuid;
    
    struct destroy_response_payload observed = {0};
    
    int result = kmip_decode_destroy_response_payload(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_destroy_response_payload(&expected, &observed),
        result,
        __func__);
    kmip_free_destroy_response_payload(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_username_password_credential(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[48] = {
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x28, 
        0x42, 0x00, 0x99, 0x07, 0x00, 0x00, 0x00, 0x04, 
        0x46, 0x72, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xA1, 0x07, 0x00, 0x00, 0x00, 0x09, 
        0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 
        0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[48] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string username = {0};
    username.value = "Fred";
    username.size = 4;
    struct text_string password = {0};
    password.value = "password1";
    password.size = 9;
    
    struct username_password_credential upc = {0};
    upc.username = &username;
    upc.password = &password;
    
    int result = kmip_encode_username_password_credential(&ctx, &upc);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_username_password_credential(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[48] = {
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x28, 
        0x42, 0x00, 0x99, 0x07, 0x00, 0x00, 0x00, 0x04, 
        0x46, 0x72, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xA1, 0x07, 0x00, 0x00, 0x00, 0x09, 
        0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 
        0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string username = {0};
    username.value = "Fred";
    username.size = 4;
    struct text_string password = {0};
    password.value = "password1";
    password.size = 9;
    
    struct username_password_credential expected = {0};
    expected.username = &username;
    expected.password = &password;
    
    struct username_password_credential observed = {0};
    
    int result = kmip_decode_username_password_credential(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_username_password_credential(&expected, &observed),
        result,
        __func__);
    kmip_free_username_password_credential(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_credential_username_password_credential(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[64] = {
        0x42, 0x00, 0x23, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x24, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x99, 0x07, 0x00, 0x00, 0x00, 0x06, 
        0x42, 0x61, 0x72, 0x6E, 0x65, 0x79, 0x00, 0x00, 
        0x42, 0x00, 0xA1, 0x07, 0x00, 0x00, 0x00, 0x07, 
        0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x32, 0x00
    };
    
    uint8 observed[64] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string username = {0};
    username.value = "Barney";
    username.size = 6;
    struct text_string password = {0};
    password.value = "secret2";
    password.size = 7;
    
    struct username_password_credential upc = {0};
    upc.username = &username;
    upc.password = &password;
    
    struct credential c = {0};
    c.credential_type = KMIP_CRED_USERNAME_AND_PASSWORD;
    c.credential_value = &upc;
    
    int result = kmip_encode_credential(&ctx, &c);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_credential_username_password_credential(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[64] = {
        0x42, 0x00, 0x23, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x24, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x99, 0x07, 0x00, 0x00, 0x00, 0x06, 
        0x42, 0x61, 0x72, 0x6E, 0x65, 0x79, 0x00, 0x00, 
        0x42, 0x00, 0xA1, 0x07, 0x00, 0x00, 0x00, 0x07, 
        0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x32, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string username = {0};
    username.value = "Barney";
    username.size = 6;
    struct text_string password = {0};
    password.value = "secret2";
    password.size = 7;
    
    struct username_password_credential upc = {0};
    upc.username = &username;
    upc.password = &password;
    
    struct credential expected = {0};
    expected.credential_type = KMIP_CRED_USERNAME_AND_PASSWORD;
    expected.credential_value = &upc;

    struct credential observed = {0};
    
    int result = kmip_decode_credential(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_credential(&expected, &observed),
        result,
        __func__);
    kmip_free_credential(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_authentication_username_password_credential(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[80] = {
        0x42, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x23, 0x01, 0x00, 0x00, 0x00, 0x40, 
        0x42, 0x00, 0x24, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x28, 
        0x42, 0x00, 0x99, 0x07, 0x00, 0x00, 0x00, 0x04, 
        0x46, 0x72, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xA1, 0x07, 0x00, 0x00, 0x00, 0x09, 
        0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 
        0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[80] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string username = {0};
    username.value = "Fred";
    username.size = 4;
    struct text_string password = {0};
    password.value = "password1";
    password.size = 9;
    
    struct username_password_credential upc = {0};
    upc.username = &username;
    upc.password = &password;
    
    struct credential c = {0};
    c.credential_type = KMIP_CRED_USERNAME_AND_PASSWORD;
    c.credential_value = &upc;
    
    struct authentication a = {0};
    a.credential = &c;
    
    int result = kmip_encode_authentication(&ctx, &a);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_authentication_username_password_credential(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[80] = {
        0x42, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x23, 0x01, 0x00, 0x00, 0x00, 0x40, 
        0x42, 0x00, 0x24, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x28, 
        0x42, 0x00, 0x99, 0x07, 0x00, 0x00, 0x00, 0x04, 
        0x46, 0x72, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xA1, 0x07, 0x00, 0x00, 0x00, 0x09, 
        0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 
        0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string username = {0};
    username.value = "Fred";
    username.size = 4;
    struct text_string password = {0};
    password.value = "password1";
    password.size = 9;
    
    struct username_password_credential upc = {0};
    upc.username = &username;
    upc.password = &password;
    
    struct credential c = {0};
    c.credential_type = KMIP_CRED_USERNAME_AND_PASSWORD;
    c.credential_value = &upc;
    
    struct authentication expected = {0};
    expected.credential = &c;
    
    struct authentication observed = {0};
    
    int result = kmip_decode_authentication(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_authentication(&expected, &observed),
        result,
        __func__);
    kmip_free_authentication(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_request_header(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[168] = {
        0x42, 0x00, 0x77, 0x01, 0x00, 0x00, 0x00, 0xA0, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x40, 
        0x42, 0x00, 0x23, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x24, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x99, 0x07, 0x00, 0x00, 0x00, 0x06, 
        0x42, 0x61, 0x72, 0x6E, 0x65, 0x79, 0x00, 0x00, 
        0x42, 0x00, 0xA1, 0x07, 0x00, 0x00, 0x00, 0x07, 
        0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x32, 0x00, 
        0x42, 0x00, 0x0E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x10, 0x06, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[168] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    struct text_string username = {0};
    username.value = "Barney";
    username.size = 6;
    struct text_string password = {0};
    password.value = "secret2";
    password.size = 7;
    
    struct username_password_credential upc = {0};
    upc.username = &username;
    upc.password = &password;
    
    struct credential c = {0};
    c.credential_type = KMIP_CRED_USERNAME_AND_PASSWORD;
    c.credential_value = &upc;
    
    struct authentication a = {0};
    a.credential = &c;
    
    struct request_header rh = {0};
    kmip_init_request_header(&rh);
    
    rh.protocol_version = &pv;
    rh.authentication = &a;
    rh.batch_error_continuation_option = KMIP_BATCH_CONTINUE;
    rh.batch_order_option = KMIP_TRUE;
    rh.batch_count = 2;
    
    int result = kmip_encode_request_header(&ctx, &rh);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_request_header(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[168] = {
        0x42, 0x00, 0x77, 0x01, 0x00, 0x00, 0x00, 0xA0, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x40, 
        0x42, 0x00, 0x23, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x24, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x99, 0x07, 0x00, 0x00, 0x00, 0x06, 
        0x42, 0x61, 0x72, 0x6E, 0x65, 0x79, 0x00, 0x00, 
        0x42, 0x00, 0xA1, 0x07, 0x00, 0x00, 0x00, 0x07, 
        0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x32, 0x00, 
        0x42, 0x00, 0x0E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x10, 0x06, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    struct text_string username = {0};
    username.value = "Barney";
    username.size = 6;
    struct text_string password = {0};
    password.value = "secret2";
    password.size = 7;
    
    struct username_password_credential upc = {0};
    upc.username = &username;
    upc.password = &password;
    
    struct credential c = {0};
    c.credential_type = KMIP_CRED_USERNAME_AND_PASSWORD;
    c.credential_value = &upc;
    
    struct authentication a = {0};
    a.credential = &c;
    
    struct request_header expected = {0};
    kmip_init_request_header(&expected);
    
    expected.protocol_version = &pv;
    expected.authentication = &a;
    expected.batch_error_continuation_option = KMIP_BATCH_CONTINUE;
    expected.batch_order_option = KMIP_TRUE;
    expected.batch_count = 2;
    
    struct request_header observed = {0};
    kmip_init_request_header(&observed);
    
    int result = kmip_decode_request_header(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_request_header(&expected, &observed),
        result,
        __func__);
    kmip_free_request_header(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_response_header(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[80] = {
        0x42, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x4F, 0x9A, 0x54, 0xE5, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[80] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    struct response_header rh = {0};
    kmip_init_response_header(&rh);
    
    rh.protocol_version = &pv;
    rh.time_stamp = 1335514341;
    rh.batch_count = 1;
    
    int result = kmip_encode_response_header(&ctx, &rh);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_response_header(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[80] = {
        0x42, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x4F, 0x9A, 0x54, 0xE5, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    struct response_header expected = {0};
    kmip_init_response_header(&expected);
    
    expected.protocol_version = &pv;
    expected.time_stamp = 1335514341;
    expected.batch_count = 1;
    
    struct response_header observed = {0};
    kmip_init_response_header(&observed);
    
    int result = kmip_decode_response_header(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_response_header(&expected, &observed),
        result,
        __func__);
    kmip_free_response_header(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_request_batch_item_get_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[80] = {
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[80] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    struct get_request_payload grp = {0};
    grp.unique_identifier = &uuid;
    
    struct request_batch_item rbi = {0};
    kmip_init_request_batch_item(&rbi);
    rbi.operation = KMIP_OP_GET;
    rbi.request_payload = &grp;
    
    int result = kmip_encode_request_batch_item(&ctx, &rbi);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_request_batch_item_get_payload_kmip_2_0(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following set of values:
    *  Batch Item
    *      Operation - Get
    *      Ephemeral - False
    *      Request Payload
    *          Unique Identifier - 49a1ca88-6bea-4fb2-b450-7e58802c3038
    */
    uint8 expected[96] = {
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x58,
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x54, 0x06, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24,
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38,
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66,
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D,
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63,
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00
    };

    uint8 observed[96] = {0};
    KMIP ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_2_0);

    TextString uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;

    GetRequestPayload grp = {0};
    grp.unique_identifier = &uuid;

    RequestBatchItem rbi = {0};
    kmip_init_request_batch_item(&rbi);
    rbi.operation = KMIP_OP_GET;
    rbi.ephemeral = KMIP_FALSE;
    rbi.request_payload = &grp;

    int result = kmip_encode_request_batch_item(&ctx, &rbi);
    result = report_encoding_test_result(tracker, &ctx, expected, observed, result, __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_request_batch_item_get_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[80] = {
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    struct get_request_payload grp = {0};
    grp.unique_identifier = &uuid;
    
    struct request_batch_item expected = {0};
    kmip_init_request_batch_item(&expected);
    expected.operation = KMIP_OP_GET;
    expected.request_payload = &grp;
    
    struct request_batch_item observed = {0};
    kmip_init_request_batch_item(&observed);
    
    int result = kmip_decode_request_batch_item(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_request_batch_item(&expected, &observed),
        result,
        __func__);
    kmip_free_request_batch_item(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_request_batch_item_get_payload_kmip_2_0(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following set of values:
    *  Batch Item
    *      Operation - Get
    *      Ephemeral - False
    *      Request Payload
    *          Unique Identifier - 49a1ca88-6bea-4fb2-b450-7e58802c3038
    */
    uint8 encoding[96] = {
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x58,
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x54, 0x06, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x30,
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24,
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38,
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66,
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D,
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63,
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00
    };

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);

    TextString uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;

    GetRequestPayload grp = {0};
    grp.unique_identifier = &uuid;

    RequestBatchItem expected = {0};
    kmip_init_request_batch_item(&expected);
    expected.operation = KMIP_OP_GET;
    expected.ephemeral = KMIP_FALSE;
    expected.request_payload = &grp;

    RequestBatchItem observed = {0};
    kmip_init_request_batch_item(&observed);

    int result = kmip_decode_request_batch_item(&ctx, &observed);
    int comparison = kmip_compare_request_batch_item(&expected, &observed);
    if(!comparison)
    {
        kmip_print_request_batch_item(1, &expected);
        kmip_print_request_batch_item(1, &observed);
    }
    result = report_decoding_test_result(tracker, &ctx, comparison, result, __func__);

    kmip_free_request_batch_item(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_response_batch_item_get_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[216] = {
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0xD0, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x7F, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0xA8, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x8F, 0x01, 0x00, 0x00, 0x00, 0x60, 
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x58, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x18, 
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[216] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    uint8 value[24] = {
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8
    };
    
    struct byte_string v = {0};
    v.value = value;
    v.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &v;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_RAW;
    kb.key_value = &kv;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_TRIPLE_DES;
    kb.cryptographic_length = 168;
    
    struct symmetric_key key = {0};
    key.key_block = &kb;
    
    struct get_response_payload grp = {0};
    grp.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    grp.unique_identifier = &uuid;
    grp.object = &key;
    
    struct response_batch_item rbi = {0};
    rbi.operation = KMIP_OP_GET;
    rbi.result_status = KMIP_STATUS_SUCCESS;
    rbi.response_payload = &grp;
    
    int result = kmip_encode_response_batch_item(&ctx, &rbi);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_response_batch_item_get_payload(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[216] = {
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0xD0, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x7F, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0xA8, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x8F, 0x01, 0x00, 0x00, 0x00, 0x60, 
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x58, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x18, 
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    uint8 value[24] = {
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8
    };
    
    struct byte_string v = {0};
    v.value = value;
    v.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &v;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_RAW;
    kb.key_value = &kv;
    kb.key_value_type = KMIP_TYPE_STRUCTURE;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_TRIPLE_DES;
    kb.cryptographic_length = 168;
    
    struct symmetric_key key = {0};
    key.key_block = &kb;
    
    struct get_response_payload grp = {0};
    grp.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    grp.unique_identifier = &uuid;
    grp.object = &key;
    
    struct response_batch_item expected = {0};
    expected.operation = KMIP_OP_GET;
    expected.result_status = KMIP_STATUS_SUCCESS;
    expected.response_payload = &grp;
    
    struct response_batch_item observed = {0};
    
    int result = kmip_decode_response_batch_item(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_response_batch_item(&expected, &observed),
        result,
        __func__);
    kmip_free_response_batch_item(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_request_message_get(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[152] = {
        0x42, 0x00, 0x78, 0x01, 0x00, 0x00, 0x00, 0x90, 
        0x42, 0x00, 0x77, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[152] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    struct request_header rh = {0};
    kmip_init_request_header(&rh);
    
    rh.protocol_version = &pv;
    rh.batch_count = 1;
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    struct get_request_payload grp = {0};
    grp.unique_identifier = &uuid;
    
    struct request_batch_item rbi = {0};
    kmip_init_request_batch_item(&rbi);
    rbi.operation = KMIP_OP_GET;
    rbi.request_payload = &grp;
    
    struct request_message rm = {0};
    rm.request_header = &rh;
    rm.batch_items = &rbi;
    rm.batch_count = 1;
    
    int result = kmip_encode_request_message(&ctx, &rm);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_request_message_get(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[152] = {
        0x42, 0x00, 0x78, 0x01, 0x00, 0x00, 0x00, 0x90, 
        0x42, 0x00, 0x77, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    struct request_header rh = {0};
    kmip_init_request_header(&rh);
    
    rh.protocol_version = &pv;
    rh.batch_count = 1;
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    struct get_request_payload grp = {0};
    grp.unique_identifier = &uuid;
    
    struct request_batch_item rbi = {0};
    kmip_init_request_batch_item(&rbi);
    rbi.operation = KMIP_OP_GET;
    rbi.request_payload = &grp;
    
    struct request_message expected = {0};
    expected.request_header = &rh;
    expected.batch_items = &rbi;
    expected.batch_count = 1;
    
    struct request_message observed = {0};
    
    int result = kmip_decode_request_message(&ctx, &observed);
    int comparison = kmip_compare_request_message(&expected, &observed);
    if(!comparison)
    {
        kmip_print_request_message(&expected);
        kmip_print_request_message(&observed);
    }
    result = report_decoding_test_result(tracker, &ctx, comparison, result, __func__);

    kmip_free_request_message(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_response_message_get(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[304] = {
        0x42, 0x00, 0x7B, 0x01, 0x00, 0x00, 0x01, 0x28, 
        0x42, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x4F, 0x9A, 0x54, 0xE7, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0xD0, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x7F, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0xA8, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x8F, 0x01, 0x00, 0x00, 0x00, 0x60, 
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x58, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x18, 
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[304] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    struct response_header rh = {0};
    kmip_init_response_header(&rh);
    
    rh.protocol_version = &pv;
    rh.time_stamp = 1335514343;
    rh.batch_count = 1;
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    uint8 value[24] = {
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8
    };
    
    struct byte_string v = {0};
    v.value = value;
    v.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &v;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_RAW;
    kb.key_value = &kv;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_TRIPLE_DES;
    kb.cryptographic_length = 168;
    
    struct symmetric_key key = {0};
    key.key_block = &kb;
    
    struct get_response_payload grp = {0};
    grp.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    grp.unique_identifier = &uuid;
    grp.object = &key;
    
    struct response_batch_item rbi = {0};
    rbi.operation = KMIP_OP_GET;
    rbi.result_status = KMIP_STATUS_SUCCESS;
    rbi.response_payload = &grp;
    
    struct response_message rm = {0};
    rm.response_header = &rh;
    rm.batch_items = &rbi;
    rm.batch_count = 1;
    
    int result = kmip_encode_response_message(&ctx, &rm);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_response_message_get(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[304] = {
        0x42, 0x00, 0x7B, 0x01, 0x00, 0x00, 0x01, 0x28, 
        0x42, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x4F, 0x9A, 0x54, 0xE7, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0xD0, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x7F, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0xA8, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x8F, 0x01, 0x00, 0x00, 0x00, 0x60, 
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x58, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x18, 
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    struct response_header rh = {0};
    kmip_init_response_header(&rh);
    
    rh.protocol_version = &pv;
    rh.time_stamp = 1335514343;
    rh.batch_count = 1;
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    uint8 value[24] = {
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8
    };
    
    struct byte_string v = {0};
    v.value = value;
    v.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &v;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_RAW;
    kb.key_value = &kv;
    kb.key_value_type = KMIP_TYPE_STRUCTURE;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_TRIPLE_DES;
    kb.cryptographic_length = 168;
    
    struct symmetric_key key = {0};
    key.key_block = &kb;
    
    struct get_response_payload grp = {0};
    grp.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    grp.unique_identifier = &uuid;
    grp.object = &key;
    
    struct response_batch_item rbi = {0};
    rbi.operation = KMIP_OP_GET;
    rbi.result_status = KMIP_STATUS_SUCCESS;
    rbi.response_payload = &grp;
    
    struct response_message expected = {0};
    expected.response_header = &rh;
    expected.batch_items = &rbi;
    expected.batch_count = 1;
    
    struct response_message observed = {0};
    
    int result = kmip_decode_response_message(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_response_message(&expected, &observed),
        result,
        __func__);
    kmip_free_response_message(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_attributes(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following set of values:
    *  Attributes
    *      Cryptographic Algorithm - AES
    *      Cryptographic Length - 128
    */
    uint8 expected[40] = {
        0x42, 0x01, 0x25, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[40] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_2_0);

    LinkedList attribute_list = {0};

    LinkedListItem item_1 = {0};
    Attribute attr_1 = {0};
    kmip_init_attribute(&attr_1);
    enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES;
    attr_1.type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    attr_1.value = &algorithm;
    item_1.data = &attr_1;

    LinkedListItem item_2 = {0};
    Attribute attr_2 = {0};
    kmip_init_attribute(&attr_2);
    int32 length = 128;
    attr_2.type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    attr_2.value = &length;
    item_2.data = &attr_2;

    kmip_linked_list_enqueue(&attribute_list, &item_1);
    kmip_linked_list_enqueue(&attribute_list, &item_2);

    Attributes attributes = {0};
    attributes.attribute_list = &attribute_list;

    int result = kmip_encode_attributes(&ctx, &attributes);
    result = report_encoding_test_result(tracker, &ctx, expected, observed, result, __func__);

    kmip_destroy(&ctx);

    return(result);
}

int
test_encode_attributes_with_invalid_kmip_version(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 observed[40] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_4);

    Attributes attributes = {0};

    int result = kmip_encode_attributes(&ctx, &attributes);
    kmip_destroy(&ctx);

    result = report_result(tracker, result, KMIP_INVALID_FOR_VERSION, __func__);
    return(result);
}

int
test_encode_attribute_v2_unique_identifier(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  Unique Identifier - fb4b5b9c-6188-4c63-8142-fe9c328129fc
    */
    uint8 expected[48] = {
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24,
        0x66, 0x62, 0x34, 0x62, 0x35, 0x62, 0x39, 0x63,
        0x2D, 0x36, 0x31, 0x38, 0x38, 0x2D, 0x34, 0x63,
        0x36, 0x33, 0x2D, 0x38, 0x31, 0x34, 0x32, 0x2D,
        0x66, 0x65, 0x39, 0x63, 0x33, 0x32, 0x38, 0x31,
        0x32, 0x39, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00
    };

    uint8 observed[48] = {0};
    KMIP ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_2_0);

    Attribute attribute = {0};
    kmip_init_attribute(&attribute);
    TextString unique_identifier = {0};
    unique_identifier.value = "fb4b5b9c-6188-4c63-8142-fe9c328129fc";
    unique_identifier.size = 36;
    attribute.type = KMIP_ATTR_UNIQUE_IDENTIFIER;
    attribute.value = &unique_identifier;

    int result = kmip_encode_attribute_v2(&ctx, &attribute);
    result = report_encoding_test_result(tracker, &ctx, expected, observed, result, __func__);

    kmip_destroy(&ctx);

    return(result);
}

int
test_encode_attribute_v2_name(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  Name
    *      Value - Template1
    *      Type - Uninterpreted Text String
    */
    uint8 expected[48] = {
        0x42, 0x00, 0x53, 0x01, 0x00, 0x00, 0x00, 0x28,
        0x42, 0x00, 0x55, 0x07, 0x00, 0x00, 0x00, 0x09,
        0x54, 0x65, 0x6D, 0x70, 0x6C, 0x61, 0x74, 0x65,
        0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };

    uint8 observed[48] = {0};
    KMIP ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_2_0);

    Attribute attribute = {0};
    kmip_init_attribute(&attribute);
    TextString name_value = {0};
    name_value.value = "Template1";
    name_value.size = 9;
    Name name = {0};
    name.value = &name_value;
    name.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING;

    attribute.type = KMIP_ATTR_NAME;
    attribute.value = &name;

    int result = kmip_encode_attribute_v2(&ctx, &attribute);
    result = report_encoding_test_result(tracker, &ctx, expected, observed, result, __func__);

    kmip_destroy(&ctx);

    return(result);
}

int
test_encode_attribute_v2_object_type(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  Object Type - Symmetric Key
    */
    uint8 expected[16] = {
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
    };

    uint8 observed[16] = {0};
    KMIP ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_2_0);

    Attribute attribute = {0};
    kmip_init_attribute(&attribute);
    enum object_type object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    attribute.type = KMIP_ATTR_OBJECT_TYPE;
    attribute.value = &object_type;

    int result = kmip_encode_attribute_v2(&ctx, &attribute);
    result = report_encoding_test_result(tracker, &ctx, expected, observed, result, __func__);

    kmip_destroy(&ctx);

    return(result);
}

int
test_encode_attribute_v2_cryptographic_algorithm(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  Cryptographic Algorithm - AES
    */
    uint8 expected[16] = {
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00
    };

    uint8 observed[16] = {0};
    KMIP ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_2_0);

    Attribute attribute = {0};
    kmip_init_attribute(&attribute);
    enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES;
    attribute.type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    attribute.value = &algorithm;

    int result = kmip_encode_attribute_v2(&ctx, &attribute);
    result = report_encoding_test_result(tracker, &ctx, expected, observed, result, __func__);

    kmip_destroy(&ctx);

    return(result);
}

int
test_encode_attribute_v2_cryptographic_length(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  Cryptographic Length - 128
    */
    uint8 expected[16] = {
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00
    };

    uint8 observed[16] = {0};
    KMIP ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_2_0);

    Attribute attribute = {0};
    kmip_init_attribute(&attribute);
    int32 length = 128;
    attribute.type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    attribute.value = &length;

    int result = kmip_encode_attribute_v2(&ctx, &attribute);
    result = report_encoding_test_result(tracker, &ctx, expected, observed, result, __func__);

    kmip_destroy(&ctx);

    return(result);
}

int
test_encode_attribute_v2_cryptographic_usage_mask(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  Cryptographic Usage Mask - Encrypt | Decrypt
    */
    uint8 expected[16] = {
        0x42, 0x00, 0x2C, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00
    };

    uint8 observed[16] = {0};
    KMIP ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_2_0);

    Attribute attribute = {0};
    kmip_init_attribute(&attribute);
    int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT;
    attribute.type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK;
    attribute.value = &mask;

    int result = kmip_encode_attribute_v2(&ctx, &attribute);
    result = report_encoding_test_result(tracker, &ctx, expected, observed, result, __func__);

    kmip_destroy(&ctx);

    return(result);
}

int
test_encode_attribute_v2_state(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  State - Active
    */
    uint8 expected[16] = {
        0x42, 0x00, 0x8D, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
    };

    uint8 observed[16] = {0};
    KMIP ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_2_0);

    Attribute attribute = {0};
    kmip_init_attribute(&attribute);
    enum state state = KMIP_STATE_ACTIVE;
    attribute.type = KMIP_ATTR_STATE;
    attribute.value = &state;

    int result = kmip_encode_attribute_v2(&ctx, &attribute);
    result = report_encoding_test_result(tracker, &ctx, expected, observed, result, __func__);

    kmip_destroy(&ctx);

    return(result);
}

int
test_encode_attribute_v2_unsupported_attribute(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[16] = {0};

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);

    Attribute attribute = {0};
    attribute.type = -1;
    int result = kmip_encode_attribute_v2(&ctx, &attribute);
    if(result != KMIP_ERROR_ATTR_UNSUPPORTED)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_destroy(&ctx);

    TEST_PASSED(tracker, __func__);
}

int
test_decode_attributes(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following set of values:
    *  Attributes
    *      Cryptographic Algorithm - AES
    *      Cryptographic Length - 128
    */
    uint8 encoding[40] = {
        0x42, 0x01, 0x25, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00
    };

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);

    LinkedList attribute_list = {0};

    LinkedListItem item_1 = {0};
    Attribute attr_1 = {0};
    kmip_init_attribute(&attr_1);
    enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES;
    attr_1.type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    attr_1.value = &algorithm;
    item_1.data = &attr_1;

    LinkedListItem item_2 = {0};
    Attribute attr_2 = {0};
    kmip_init_attribute(&attr_2);
    int32 length = 128;
    attr_2.type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    attr_2.value = &length;
    item_2.data = &attr_2;

    kmip_linked_list_enqueue(&attribute_list, &item_1);
    kmip_linked_list_enqueue(&attribute_list, &item_2);

    Attributes expected = {0};
    expected.attribute_list = &attribute_list;

    Attributes observed = {0};
    int result = kmip_decode_attributes(&ctx, &observed);
    int comparison = kmip_compare_attributes(&expected, &observed);
    if(!comparison)
    {
        kmip_print_attributes(1, &expected);
        kmip_print_attributes(1, &observed);
    }
    result = report_decoding_test_result(tracker, &ctx, comparison, result, __func__);

    kmip_free_attributes(&ctx, &observed);
    kmip_destroy(&ctx);

    return(result);
}

int
test_decode_attributes_with_invalid_kmip_version(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[] = {0};

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_4);

    Attributes observed = {0};
    int result = kmip_decode_attributes(&ctx, &observed);

    kmip_free_attributes(&ctx, &observed);
    kmip_destroy(&ctx);

    result = report_result(tracker, result, KMIP_INVALID_FOR_VERSION, __func__);
    return(result);
}

int
test_decode_attribute_v2_unique_identifier(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  Unique Identifier - fb4b5b9c-6188-4c63-8142-fe9c328129fc
    */
    uint8 encoding[48] = {
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24,
        0x66, 0x62, 0x34, 0x62, 0x35, 0x62, 0x39, 0x63,
        0x2D, 0x36, 0x31, 0x38, 0x38, 0x2D, 0x34, 0x63,
        0x36, 0x33, 0x2D, 0x38, 0x31, 0x34, 0x32, 0x2D,
        0x66, 0x65, 0x39, 0x63, 0x33, 0x32, 0x38, 0x31,
        0x32, 0x39, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00
    };

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);

    Attribute expected = {0};
    kmip_init_attribute(&expected);
    TextString unique_identifier = {0};
    unique_identifier.value = "fb4b5b9c-6188-4c63-8142-fe9c328129fc";
    unique_identifier.size = 36;
    expected.type = KMIP_ATTR_UNIQUE_IDENTIFIER;
    expected.value = &unique_identifier;

    Attribute observed = {0};
    int result = kmip_decode_attribute_v2(&ctx, &observed);
    int comparison = kmip_compare_attribute(&expected, &observed);
    if(!comparison)
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, &observed);
    }
    result = report_decoding_test_result(tracker, &ctx, comparison, result, __func__);

    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);

    return(result);
}

int
test_decode_attribute_v2_name(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  Name
    *      Value - Template1
    *      Type - Uninterpreted Text String
    */
    uint8 encoding[48] = {
        0x42, 0x00, 0x53, 0x01, 0x00, 0x00, 0x00, 0x28,
        0x42, 0x00, 0x55, 0x07, 0x00, 0x00, 0x00, 0x09,
        0x54, 0x65, 0x6D, 0x70, 0x6C, 0x61, 0x74, 0x65,
        0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);

    Attribute expected = {0};
    kmip_init_attribute(&expected);
    TextString name_value = {0};
    name_value.value = "Template1";
    name_value.size = 9;
    Name name = {0};
    name.value = &name_value;
    name.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING;

    expected.type = KMIP_ATTR_NAME;
    expected.value = &name;

    Attribute observed = {0};
    int result = kmip_decode_attribute_v2(&ctx, &observed);
    int comparison = kmip_compare_attribute(&expected, &observed);
    if(!comparison)
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, &observed);
    }
    result = report_decoding_test_result(tracker, &ctx, comparison, result, __func__);

    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);

    return(result);
}

int
test_decode_attribute_v2_object_type(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  Object Type - Symmetric Key
    */
    uint8 encoding[16] = {
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
    };

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);

    Attribute expected = {0};
    kmip_init_attribute(&expected);
    enum object_type object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    expected.type = KMIP_ATTR_OBJECT_TYPE;
    expected.value = &object_type;

    Attribute observed = {0};
    int result = kmip_decode_attribute_v2(&ctx, &observed);
    int comparison = kmip_compare_attribute(&expected, &observed);
    if(!comparison)
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, &observed);
    }
    result = report_decoding_test_result(tracker, &ctx, comparison, result, __func__);

    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);

    return(result);
}

int
test_decode_attribute_v2_cryptographic_algorithm(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  Cryptographic Algorithm - AES
    */
    uint8 encoding[16] = {
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00
    };

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);

    Attribute expected = {0};
    kmip_init_attribute(&expected);
    enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES;
    expected.type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    expected.value = &algorithm;

    Attribute observed = {0};
    int result = kmip_decode_attribute_v2(&ctx, &observed);
    int comparison = kmip_compare_attribute(&expected, &observed);
    if(!comparison)
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, &observed);
    }
    result = report_decoding_test_result(tracker, &ctx, comparison, result, __func__);

    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);

    return(result);
}

int
test_decode_attribute_v2_cryptographic_length(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  Cryptographic Length - 128
    */
    uint8 encoding[16] = {
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00
    };

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);

    Attribute expected = {0};
    kmip_init_attribute(&expected);
    int32 length = 128;
    expected.type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    expected.value = &length;

    Attribute observed = {0};
    int result = kmip_decode_attribute_v2(&ctx, &observed);
    int comparison = kmip_compare_attribute(&expected, &observed);
    if(!comparison)
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, &observed);
    }
    result = report_decoding_test_result(tracker, &ctx, comparison, result, __func__);

    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);

    return(result);
}

int
test_decode_attribute_v2_cryptographic_usage_mask(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  Cryptographic Usage Mask - Encrypt | Decrypt
    */
    uint8 encoding[16] = {
        0x42, 0x00, 0x2C, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00
    };

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);

    Attribute expected = {0};
    kmip_init_attribute(&expected);
    int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT;
    expected.type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK;
    expected.value = &mask;

    Attribute observed = {0};
    int result = kmip_decode_attribute_v2(&ctx, &observed);
    int comparison = kmip_compare_attribute(&expected, &observed);
    if(!comparison)
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, &observed);
    }
    result = report_decoding_test_result(tracker, &ctx, comparison, result, __func__);

    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);

    return(result);
}

int
test_decode_attribute_v2_state(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following value:
    *  State - Active
    */
    uint8 encoding[16] = {
        0x42, 0x00, 0x8D, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
    };

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);

    Attribute expected = {0};
    kmip_init_attribute(&expected);
    enum state state = KMIP_STATE_ACTIVE;
    expected.type = KMIP_ATTR_STATE;
    expected.value = &state;

    Attribute observed = {0};
    int result = kmip_decode_attribute_v2(&ctx, &observed);
    int comparison = kmip_compare_attribute(&expected, &observed);
    if(!comparison)
    {
        kmip_print_attribute(1, &expected);
        kmip_print_attribute(1, &observed);
    }
    result = report_decoding_test_result(tracker, &ctx, comparison, result, __func__);

    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);

    return(result);
}

int
test_decode_attribute_v2_unsupported_attribute(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[3] = {0x42, 0x00, 0x00};

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);

    Attribute observed = {0};
    int result = kmip_decode_attribute_v2(&ctx, &observed);
    if(result != KMIP_ERROR_ATTR_UNSUPPORTED)
    {
        TEST_FAILED(tracker, __func__, __LINE__);
    }

    kmip_free_attribute(&ctx, &observed);
    kmip_destroy(&ctx);

    TEST_PASSED(tracker, __func__);
}

int
test_encode_template_attribute(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[288] = {
        0x42, 0x00, 0x91, 0x01, 0x00, 0x00, 0x01, 0x18, 
        0x42, 0x00, 0x53, 0x01, 0x00, 0x00, 0x00, 0x28, 
        0x42, 0x00, 0x55, 0x07, 0x00, 0x00, 0x00, 0x09, 
        0x54, 0x65, 0x6D, 0x70, 0x6C, 0x61, 0x74, 0x65, 
        0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x17, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x6C, 
        0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x14, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x4C, 0x65, 
        0x6E, 0x67, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x55, 0x73, 
        0x61, 0x67, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x6B, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x04, 
        0x4E, 0x61, 0x6D, 0x65, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x55, 0x07, 0x00, 0x00, 0x00, 0x04, 
        0x4B, 0x65, 0x79, 0x31, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[288] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct text_string v = {0};
    v.value = "Template1";
    v.size = 9;
    
    struct name n = {0};
    n.value = &v;
    n.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING;
    
    struct attribute a[4] = {{0}};
    for(int i = 0; i < 4; i++)
    {
        kmip_init_attribute(&a[i]);
    }
    
    enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES;
    a[0].type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    a[0].value = &algorithm;
    
    int32 length = 128;
    a[1].type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    a[1].value = &length;
    
    int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT;
    a[2].type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK;
    a[2].value = &mask;
    
    struct text_string value = {0};
    value.value = "Key1";
    value.size = 4;
    
    struct name name = {0};
    name.value = &value;
    name.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING;
    a[3].type = KMIP_ATTR_NAME;
    a[3].value = &name;
    
    struct template_attribute ta = {0};
    ta.names = &n;
    ta.name_count = 1;
    ta.attributes = a;
    ta.attribute_count = ARRAY_LENGTH(a);
    
    int result = kmip_encode_template_attribute(&ctx, &ta);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_template_attribute(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[288] = {
        0x42, 0x00, 0x91, 0x01, 0x00, 0x00, 0x01, 0x18, 
        0x42, 0x00, 0x53, 0x01, 0x00, 0x00, 0x00, 0x28, 
        0x42, 0x00, 0x55, 0x07, 0x00, 0x00, 0x00, 0x09, 
        0x54, 0x65, 0x6D, 0x70, 0x6C, 0x61, 0x74, 0x65, 
        0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x17, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x6C, 
        0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x14, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x4C, 0x65, 
        0x6E, 0x67, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x55, 0x73, 
        0x61, 0x67, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x6B, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x04, 
        0x4E, 0x61, 0x6D, 0x65, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x55, 0x07, 0x00, 0x00, 0x00, 0x04, 
        0x4B, 0x65, 0x79, 0x31, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_0);
    
    struct text_string v = {0};
    v.value = "Template1";
    v.size = 9;
    
    struct name n = {0};
    n.value = &v;
    n.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING;
    
    struct attribute a[4] = {{0}};
    for(int i = 0; i < 4; i++)
    {
        kmip_init_attribute(&a[i]);
    }
    
    enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES;
    a[0].type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    a[0].value = &algorithm;
    
    int32 length = 128;
    a[1].type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    a[1].value = &length;
    
    int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT;
    a[2].type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK;
    a[2].value = &mask;
    
    struct text_string value = {0};
    value.value = "Key1";
    value.size = 4;
    
    struct name name = {0};
    name.value = &value;
    name.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING;
    a[3].type = KMIP_ATTR_NAME;
    a[3].value = &name;
    
    struct template_attribute expected = {0};
    expected.names = &n;
    expected.name_count = 1;
    expected.attributes = a;
    expected.attribute_count = ARRAY_LENGTH(a);
    struct template_attribute observed = {0};
    
    int result = kmip_decode_template_attribute(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_template_attribute(&expected, &observed),
        result,
        __func__);
    kmip_free_template_attribute(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

/*
The following tests cover features added in KMIP 1.1.
*/

int
test_encode_device_credential(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[144] = {
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x88, 
        0x42, 0x00, 0xB0, 0x07, 0x00, 0x00, 0x00, 0x0C, 
        0x73, 0x65, 0x72, 0x4E, 0x75, 0x6D, 0x31, 0x32, 
        0x33, 0x34, 0x35, 0x36, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xA1, 0x07, 0x00, 0x00, 0x00, 0x06, 
        0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x00, 0x00, 
        0x42, 0x00, 0xA2, 0x07, 0x00, 0x00, 0x00, 0x09, 
        0x64, 0x65, 0x76, 0x49, 0x44, 0x32, 0x32, 0x33, 
        0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xAB, 0x07, 0x00, 0x00, 0x00, 0x09, 
        0x6E, 0x65, 0x74, 0x49, 0x44, 0x39, 0x30, 0x30, 
        0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xA9, 0x07, 0x00, 0x00, 0x00, 0x0A, 
        0x6D, 0x61, 0x63, 0x68, 0x69, 0x6E, 0x65, 0x49, 
        0x44, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xAA, 0x07, 0x00, 0x00, 0x00, 0x0A, 
        0x6D, 0x65, 0x64, 0x69, 0x61, 0x49, 0x44, 0x33, 
        0x31, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[144] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_1);
    
    struct text_string dsn = {0};
    dsn.value = "serNum123456";
    dsn.size = 12;
    
    struct text_string p = {0};
    p.value = "secret";
    p.size = 6;
    
    struct text_string di = {0};
    di.value = "devID2233";
    di.size = 9;
    
    struct text_string ni = {0};
    ni.value = "netID9000";
    ni.size = 9;
    
    struct text_string mac = {0};
    mac.value = "machineID1";
    mac.size = 10;
    
    struct text_string med = {0};
    med.value = "mediaID313";
    med.size = 10;
    
    struct device_credential dc = {0};
    dc.device_serial_number = &dsn;
    dc.password = &p;
    dc.device_identifier = &di;
    dc.network_identifier = &ni;
    dc.machine_identifier = &mac;
    dc.media_identifier = &med;
    
    int result = kmip_encode_device_credential(&ctx, &dc);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_device_credential(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[144] = {
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x88, 
        0x42, 0x00, 0xB0, 0x07, 0x00, 0x00, 0x00, 0x0C, 
        0x73, 0x65, 0x72, 0x4E, 0x75, 0x6D, 0x31, 0x32, 
        0x33, 0x34, 0x35, 0x36, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xA1, 0x07, 0x00, 0x00, 0x00, 0x06, 
        0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x00, 0x00, 
        0x42, 0x00, 0xA2, 0x07, 0x00, 0x00, 0x00, 0x09, 
        0x64, 0x65, 0x76, 0x49, 0x44, 0x32, 0x32, 0x33, 
        0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xAB, 0x07, 0x00, 0x00, 0x00, 0x09, 
        0x6E, 0x65, 0x74, 0x49, 0x44, 0x39, 0x30, 0x30, 
        0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xA9, 0x07, 0x00, 0x00, 0x00, 0x0A, 
        0x6D, 0x61, 0x63, 0x68, 0x69, 0x6E, 0x65, 0x49, 
        0x44, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xAA, 0x07, 0x00, 0x00, 0x00, 0x0A, 
        0x6D, 0x65, 0x64, 0x69, 0x61, 0x49, 0x44, 0x33, 
        0x31, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_1);
    
    struct text_string dsn = {0};
    dsn.value = "serNum123456";
    dsn.size = 12;
    
    struct text_string p = {0};
    p.value = "secret";
    p.size = 6;
    
    struct text_string di = {0};
    di.value = "devID2233";
    di.size = 9;
    
    struct text_string ni = {0};
    ni.value = "netID9000";
    ni.size = 9;
    
    struct text_string mac = {0};
    mac.value = "machineID1";
    mac.size = 10;
    
    struct text_string med = {0};
    med.value = "mediaID313";
    med.size = 10;
    
    struct device_credential expected = {0};
    expected.device_serial_number = &dsn;
    expected.password = &p;
    expected.device_identifier = &di;
    expected.network_identifier = &ni;
    expected.machine_identifier = &mac;
    expected.media_identifier = &med;
    
    struct device_credential observed = {0};
    
    int result = kmip_decode_device_credential(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_device_credential(&expected, &observed),
        result,
        __func__);
    kmip_free_device_credential(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_key_wrapping_data_with_encoding_option(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[120] = {
        0x42, 0x00, 0x46, 0x01, 0x00, 0x00, 0x00, 0x70, 
        0x42, 0x00, 0x9E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x36, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35,
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D, 
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10,
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xA3, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[120] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_1);
    
    struct text_string uuid = {0};
    uuid.value = "100182d5-72b8-47aa-8383-4d97d512e98a";
    uuid.size = 36;
    
    struct cryptographic_parameters cp = {0};
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;
    
    struct encryption_key_information eki = {0};
    eki.unique_identifier = &uuid;
    eki.cryptographic_parameters = &cp;
    
    struct key_wrapping_data kwd = {0};
    kwd.wrapping_method = KMIP_WRAP_ENCRYPT;
    kwd.encryption_key_info = &eki;
    kwd.encoding_option = KMIP_ENCODE_NO_ENCODING;
    
    int result = kmip_encode_key_wrapping_data(&ctx, &kwd);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_key_wrapping_data_with_encoding_option(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[120] = {
        0x42, 0x00, 0x46, 0x01, 0x00, 0x00, 0x00, 0x70, 
        0x42, 0x00, 0x9E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x36, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35,
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D, 
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10,
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xA3, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_1);
    
    struct text_string uuid = {0};
    uuid.value = "100182d5-72b8-47aa-8383-4d97d512e98a";
    uuid.size = 36;
    
    struct cryptographic_parameters cp = {0};
    kmip_init_cryptographic_parameters(&cp);
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;
    
    struct encryption_key_information eki = {0};
    eki.unique_identifier = &uuid;
    eki.cryptographic_parameters = &cp;
    
    struct key_wrapping_data expected = {0};
    expected.wrapping_method = KMIP_WRAP_ENCRYPT;
    expected.encryption_key_info = &eki;
    expected.encoding_option = KMIP_ENCODE_NO_ENCODING;
    
    struct key_wrapping_data observed = {0};
    
    int result = kmip_decode_key_wrapping_data(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_key_wrapping_data(&expected, &observed),
        result,
        __func__);
    kmip_free_key_wrapping_data(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_key_wrapping_specification_with_encoding_option(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[120] = {
        0x42, 0x00, 0x47, 0x01, 0x00, 0x00, 0x00, 0x70, 
        0x42, 0x00, 0x9E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x36, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x31, 0x30, 0x30, 0x31, 0x38, 0x32, 0x64, 0x35, 
        0x2D, 0x37, 0x32, 0x62, 0x38, 0x2D, 0x34, 0x37, 
        0x61, 0x61, 0x2D, 0x38, 0x33, 0x38, 0x33, 0x2D, 
        0x34, 0x64, 0x39, 0x37, 0x64, 0x35, 0x31, 0x32, 
        0x65, 0x39, 0x38, 0x61, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x10, 
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xA3, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[120] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_1);
    
    struct text_string uuid = {0};
    uuid.value = "100182d5-72b8-47aa-8383-4d97d512e98a";
    uuid.size = 36;
    
    struct cryptographic_parameters cp = {0};
    cp.block_cipher_mode = KMIP_BLOCK_NIST_KEY_WRAP;
    
    struct encryption_key_information eki = {0};
    eki.unique_identifier = &uuid;
    eki.cryptographic_parameters = &cp;
    
    struct key_wrapping_specification kws = {0};
    kws.wrapping_method = KMIP_WRAP_ENCRYPT;
    kws.encryption_key_info = &eki;
    kws.encoding_option = KMIP_ENCODE_NO_ENCODING;
    
    int result = kmip_encode_key_wrapping_specification(&ctx, &kws);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

/*
The following tests cover features added in KMIP 1.2.
*/

int
test_encode_nonce(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[40] = {
        0x42, 0x00, 0xC8, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x00, 0x04,
        0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x06,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00
    };
    
    uint8 observed[40] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_2);
    
    uint8 id[4] = {0x01, 0x02, 0x03, 0x04};
    struct byte_string ni = {0};
    ni.value = id;
    ni.size = ARRAY_LENGTH(id);
    
    uint8 value[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    struct byte_string nv = {0};
    nv.value = value;
    nv.size = ARRAY_LENGTH(value);
    
    struct nonce n = {0};
    n.nonce_id = &ni;
    n.nonce_value = &nv;
    
    int result = kmip_encode_nonce(&ctx, &n);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_nonce(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[40] = {
        0x42, 0x00, 0xC8, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x00, 0x04,
        0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x06,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_2);
    
    uint8 id[4] = {0x01, 0x02, 0x03, 0x04};
    struct byte_string ni = {0};
    ni.value = id;
    ni.size = ARRAY_LENGTH(id);
    
    uint8 value[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    struct byte_string nv = {0};
    nv.value = value;
    nv.size = ARRAY_LENGTH(value);
    
    struct nonce expected = {0};
    expected.nonce_id = &ni;
    expected.nonce_value = &nv;
    
    struct nonce observed = {0};
    
    int result = kmip_decode_nonce(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_nonce(&expected, &observed),
        result,
        __func__);
    kmip_free_nonce(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_attestation_credential(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[128] = {
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x70,
        0x42, 0x00, 0xC8, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x00, 0x04,
        0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x06,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCB, 0x08, 0x00, 0x00, 0x00, 0x10,
        0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x44, 0x44,
        0x66, 0x66, 0x66, 0x66, 0x88, 0x88, 0x88, 0x88,
        0x42, 0x00, 0xCC, 0x08, 0x00, 0x00, 0x00, 0x14,
        0x11, 0x11, 0x11, 0x11, 0x33, 0x33, 0x33, 0x33,
        0x55, 0x55, 0x55, 0x55, 0x77, 0x77, 0x77, 0x77,
        0x99, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[128] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_2);
    
    uint8 nonce_id[4] = {0x01, 0x02, 0x03, 0x04};
    struct byte_string ni = {0};
    ni.value = nonce_id;
    ni.size = ARRAY_LENGTH(nonce_id);
    
    uint8 nonce_value[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    struct byte_string nv = {0};
    nv.value = nonce_value;
    nv.size = ARRAY_LENGTH(nonce_value);
    
    struct nonce n = {0};
    n.nonce_id = &ni;
    n.nonce_value = &nv;
    
    uint8 measurement[16] = {
        0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x44, 0x44,
        0x66, 0x66, 0x66, 0x66, 0x88, 0x88, 0x88, 0x88
    };
    struct byte_string am = {0};
    am.value = measurement;
    am.size = ARRAY_LENGTH(measurement);
    
    uint8 assertion[20] = {
        0x11, 0x11, 0x11, 0x11, 0x33, 0x33, 0x33, 0x33,
        0x55, 0x55, 0x55, 0x55, 0x77, 0x77, 0x77, 0x77,
        0x99, 0x99, 0x99, 0x99
    };
    struct byte_string aa = {0};
    aa.value = assertion;
    aa.size = ARRAY_LENGTH(assertion);
    
    struct attestation_credential ac = {0};
    ac.nonce = &n;
    ac.attestation_type = KMIP_ATTEST_TPM_QUOTE;
    ac.attestation_measurement = &am;
    ac.attestation_assertion = &aa;
    
    int result = kmip_encode_attestation_credential(&ctx, &ac);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_attestation_credential(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[128] = {
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x70,
        0x42, 0x00, 0xC8, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x00, 0x04,
        0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x06,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCB, 0x08, 0x00, 0x00, 0x00, 0x10,
        0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x44, 0x44,
        0x66, 0x66, 0x66, 0x66, 0x88, 0x88, 0x88, 0x88,
        0x42, 0x00, 0xCC, 0x08, 0x00, 0x00, 0x00, 0x14,
        0x11, 0x11, 0x11, 0x11, 0x33, 0x33, 0x33, 0x33,
        0x55, 0x55, 0x55, 0x55, 0x77, 0x77, 0x77, 0x77,
        0x99, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_2);
    
    uint8 nonce_id[4] = {0x01, 0x02, 0x03, 0x04};
    struct byte_string ni = {0};
    ni.value = nonce_id;
    ni.size = ARRAY_LENGTH(nonce_id);
    
    uint8 nonce_value[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    struct byte_string nv = {0};
    nv.value = nonce_value;
    nv.size = ARRAY_LENGTH(nonce_value);
    
    struct nonce n = {0};
    n.nonce_id = &ni;
    n.nonce_value = &nv;
    
    uint8 measurement[16] = {
        0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x44, 0x44,
        0x66, 0x66, 0x66, 0x66, 0x88, 0x88, 0x88, 0x88
    };
    struct byte_string am = {0};
    am.value = measurement;
    am.size = ARRAY_LENGTH(measurement);
    
    uint8 assertion[20] = {
        0x11, 0x11, 0x11, 0x11, 0x33, 0x33, 0x33, 0x33,
        0x55, 0x55, 0x55, 0x55, 0x77, 0x77, 0x77, 0x77,
        0x99, 0x99, 0x99, 0x99
    };
    struct byte_string aa = {0};
    aa.value = assertion;
    aa.size = ARRAY_LENGTH(assertion);
    
    struct attestation_credential expected = {0};
    expected.nonce = &n;
    expected.attestation_type = KMIP_ATTEST_TPM_QUOTE;
    expected.attestation_measurement = &am;
    expected.attestation_assertion = &aa;
    
    struct attestation_credential observed = {0};
    
    int result = kmip_decode_attestation_credential(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_attestation_credential(&expected, &observed),
        result,
        __func__);
    kmip_free_attestation_credential(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_request_header_with_attestation_details(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[216] = {
        0x42, 0x00, 0x77, 0x01, 0x00, 0x00, 0x00, 0xD0, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0xD3, 0x06, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x40, 
        0x42, 0x00, 0x23, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x24, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x99, 0x07, 0x00, 0x00, 0x00, 0x06, 
        0x42, 0x61, 0x72, 0x6E, 0x65, 0x79, 0x00, 0x00, 
        0x42, 0x00, 0xA1, 0x07, 0x00, 0x00, 0x00, 0x07, 
        0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x32, 0x00, 
        0x42, 0x00, 0x0E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x10, 0x06, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[216] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_2);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    struct text_string username = {0};
    username.value = "Barney";
    username.size = 6;
    struct text_string password = {0};
    password.value = "secret2";
    password.size = 7;
    
    struct username_password_credential upc = {0};
    upc.username = &username;
    upc.password = &password;
    
    struct credential c = {0};
    c.credential_type = KMIP_CRED_USERNAME_AND_PASSWORD;
    c.credential_value = &upc;
    
    struct authentication a = {0};
    a.credential = &c;
    
    enum attestation_type types[2] = {
        KMIP_ATTEST_TPM_QUOTE, 
        KMIP_ATTEST_SAML_ASSERTION
    };
    
    struct request_header rh = {0};
    kmip_init_request_header(&rh);
    
    rh.protocol_version = &pv;
    rh.attestation_capable_indicator = KMIP_TRUE;
    rh.attestation_types = types;
    rh.attestation_type_count = ARRAY_LENGTH(types);
    rh.authentication = &a;
    rh.batch_error_continuation_option = KMIP_BATCH_CONTINUE;
    rh.batch_order_option = KMIP_TRUE;
    rh.batch_count = 2;
    
    int result = kmip_encode_request_header(&ctx, &rh);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_response_header_with_attestation_details(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[152] = {
        0x42, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x00, 0x90, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x4F, 0x9A, 0x54, 0xE5,
        0x42, 0x00, 0xC8, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x00, 0x04,
        0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x06,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[152] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_2);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    uint8 id[4] = {0x01, 0x02, 0x03, 0x04};
    struct byte_string ni = {0};
    ni.value = id;
    ni.size = ARRAY_LENGTH(id);
    
    uint8 value[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    struct byte_string nv = {0};
    nv.value = value;
    nv.size = ARRAY_LENGTH(value);
    
    struct nonce n = {0};
    n.nonce_id = &ni;
    n.nonce_value = &nv;
    
    enum attestation_type types[2] = {
        KMIP_ATTEST_TPM_QUOTE,
        KMIP_ATTEST_SAML_ASSERTION
    };
    
    struct response_header rh = {0};
    kmip_init_response_header(&rh);
    
    rh.protocol_version = &pv;
    rh.time_stamp = 1335514341;
    rh.nonce = &n;
    rh.attestation_types = types;
    rh.attestation_type_count = ARRAY_LENGTH(types);
    rh.batch_count = 1;
    
    int result = kmip_encode_response_header(&ctx, &rh);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_response_header_with_attestation_details(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[152] = {
        0x42, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x00, 0x90, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x4F, 0x9A, 0x54, 0xE5,
        0x42, 0x00, 0xC8, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x00, 0x04,
        0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x06,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_2);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    uint8 id[4] = {0x01, 0x02, 0x03, 0x04};
    struct byte_string ni = {0};
    ni.value = id;
    ni.size = ARRAY_LENGTH(id);
    
    uint8 value[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    struct byte_string nv = {0};
    nv.value = value;
    nv.size = ARRAY_LENGTH(value);
    
    struct nonce n = {0};
    n.nonce_id = &ni;
    n.nonce_value = &nv;
    
    enum attestation_type types[2] = {
        KMIP_ATTEST_TPM_QUOTE,
        KMIP_ATTEST_SAML_ASSERTION
    };
    
    struct response_header expected = {0};
    kmip_init_response_header(&expected);
    
    expected.protocol_version = &pv;
    expected.time_stamp = 1335514341;
    expected.nonce = &n;
    expected.attestation_types = types;
    expected.attestation_type_count = ARRAY_LENGTH(types);
    expected.batch_count = 1;
    
    struct response_header observed = {0};
    kmip_init_response_header(&observed);
    
    int result = kmip_decode_response_header(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_response_header(&expected, &observed),
        result,
        __func__);
    kmip_free_response_header(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_cryptographic_parameters_with_digital_signature_fields(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[216] = {
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0xD0,
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x5F, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x38, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x83, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xAE, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xC5, 0x06, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
        0x42, 0x00, 0xCD, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCE, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCF, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xD2, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xD0, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xD1, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[216] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_2);
    
    struct cryptographic_parameters cp = {0};
    cp.block_cipher_mode = KMIP_BLOCK_CBC;
    cp.padding_method = KMIP_PAD_PKCS5;
    cp.hashing_algorithm = KMIP_HASH_SHA1;
    cp.key_role_type = KMIP_ROLE_KEK;
    
    cp.digital_signature_algorithm = KMIP_DIGITAL_SHA256_WITH_RSA;
    cp.cryptographic_algorithm = KMIP_CRYPTOALG_RSA;
    cp.random_iv = KMIP_TRUE;
    cp.iv_length = 128;
    cp.tag_length = 64;
    cp.fixed_field_length = 64;
    cp.invocation_field_length = 64;
    cp.counter_length = 256;
    cp.initial_counter_value = 0;
    
    int result = kmip_encode_cryptographic_parameters(&ctx, &cp);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_cryptographic_parameters_with_digital_signature_fields(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[216] = {
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0xD0,
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x5F, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x38, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x83, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xAE, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00 ,0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xC5, 0x06, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
        0x42, 0x00, 0xCD, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCE, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCF, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xD2, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xD0, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xD1, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_2);
    
    struct cryptographic_parameters expected = {0};
    kmip_init_cryptographic_parameters(&expected);
    expected.block_cipher_mode = KMIP_BLOCK_CBC;
    expected.padding_method = KMIP_PAD_PKCS5;
    expected.hashing_algorithm = KMIP_HASH_SHA1;
    expected.key_role_type = KMIP_ROLE_KEK;
    
    expected.digital_signature_algorithm = KMIP_DIGITAL_SHA256_WITH_RSA;
    expected.cryptographic_algorithm = KMIP_CRYPTOALG_RSA;
    expected.random_iv = KMIP_TRUE;
    expected.iv_length = 128;
    expected.tag_length = 64;
    expected.fixed_field_length = 64;
    expected.invocation_field_length = 64;
    expected.counter_length = 256;
    expected.initial_counter_value = 0;
    
    struct cryptographic_parameters observed = {0};
    kmip_init_cryptographic_parameters(&observed);
    
    int result = kmip_decode_cryptographic_parameters(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_cryptographic_parameters(&expected, &observed),
        result,
        __func__);
    kmip_free_cryptographic_parameters(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

/*
The following tests cover features added in KMIP 1.4.
*/

int
test_encode_cryptographic_parameters_with_mask_fields(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[312] = {
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x01, 0x30,
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x5F, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x38, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x83, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xAE, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xC5, 0x06, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
        0x42, 0x00, 0xCD, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCE, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCF, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xD2, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xD0, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xD1, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x01, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x02, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x03, 0x08, 0x00, 0x00, 0x00, 0x18, 
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8,
        0x42, 0x01, 0x04, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[312] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_4);
    
    uint8 value[24] = {
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8
    };
    struct byte_string ps = {0};
    ps.value = value;
    ps.size = ARRAY_LENGTH(value);
    
    struct cryptographic_parameters cp = {0};
    cp.block_cipher_mode = KMIP_BLOCK_CBC;
    cp.padding_method = KMIP_PAD_PKCS5;
    cp.hashing_algorithm = KMIP_HASH_SHA1;
    cp.key_role_type = KMIP_ROLE_KEK;
    
    cp.digital_signature_algorithm = KMIP_DIGITAL_SHA256_WITH_RSA;
    cp.cryptographic_algorithm = KMIP_CRYPTOALG_RSA;
    cp.random_iv = KMIP_TRUE;
    cp.iv_length = 128;
    cp.tag_length = 64;
    cp.fixed_field_length = 64;
    cp.invocation_field_length = 64;
    cp.counter_length = 256;
    cp.initial_counter_value = 0;
    
    cp.salt_length = 32;
    cp.mask_generator = KMIP_MASKGEN_MGF1;
    cp.mask_generator_hashing_algorithm = KMIP_HASH_SHA256;
    cp.p_source = &ps;
    cp.trailer_field = 1;
    
    int result = kmip_encode_cryptographic_parameters(&ctx, &cp);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_cryptographic_parameters_with_mask_fields(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[312] = {
        0x42, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x01, 0x30,
        0x42, 0x00, 0x11, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x5F, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x38, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x83, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xAE, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xC5, 0x06, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
        0x42, 0x00, 0xCD, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCE, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCF, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xD2, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xD0, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xD1, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x01, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x02, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x03, 0x08, 0x00, 0x00, 0x00, 0x18, 
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8,
        0x42, 0x01, 0x04, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_4);
    
    uint8 value[24] = {
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8
    };
    struct byte_string ps = {0};
    ps.value = value;
    ps.size = ARRAY_LENGTH(value);
    
    struct cryptographic_parameters expected = {0};
    kmip_init_cryptographic_parameters(&expected);
    
    expected.block_cipher_mode = KMIP_BLOCK_CBC;
    expected.padding_method = KMIP_PAD_PKCS5;
    expected.hashing_algorithm = KMIP_HASH_SHA1;
    expected.key_role_type = KMIP_ROLE_KEK;
    
    expected.digital_signature_algorithm = KMIP_DIGITAL_SHA256_WITH_RSA;
    expected.cryptographic_algorithm = KMIP_CRYPTOALG_RSA;
    expected.random_iv = KMIP_TRUE;
    expected.iv_length = 128;
    expected.tag_length = 64;
    expected.fixed_field_length = 64;
    expected.invocation_field_length = 64;
    expected.counter_length = 256;
    expected.initial_counter_value = 0;
    
    expected.salt_length = 32;
    expected.mask_generator = KMIP_MASKGEN_MGF1;
    expected.mask_generator_hashing_algorithm = KMIP_HASH_SHA256;
    expected.p_source = &ps;
    expected.trailer_field = 1;
    
    struct cryptographic_parameters observed = {0};
    kmip_init_cryptographic_parameters(&observed);
    
    int result = kmip_decode_cryptographic_parameters(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_cryptographic_parameters(&expected, &observed),
        result,
        __func__);
    kmip_free_cryptographic_parameters(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_get_request_payload_with_wrap_type(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[104] = {
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x60, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x37, 0x63, 0x66, 0x35, 0x32, 0x30, 0x39, 0x62, 
        0x2D, 0x36, 0x66, 0x66, 0x36, 0x2D, 0x34, 0x34, 
        0x32, 0x36, 0x2D, 0x38, 0x39, 0x39, 0x65, 0x2D, 
        0x32, 0x32, 0x62, 0x30, 0x36, 0x37, 0x38, 0x35, 
        0x39, 0x33, 0x37, 0x32, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xF8, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x41, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[104] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_4);
    
    struct text_string uuid = {0};
    uuid.value = "7cf5209b-6ff6-4426-899e-22b067859372";
    uuid.size = 36;
    
    struct get_request_payload grp = {0};
    grp.unique_identifier = &uuid;
    grp.key_format_type = KMIP_KEYFORMAT_PKCS1;
    grp.key_compression_type = KMIP_KEYCOMP_EC_PUB_UNCOMPRESSED;
    
    grp.key_wrap_type = KMIP_WRAPTYPE_NOT_WRAPPED;
    
    int result = kmip_encode_get_request_payload(&ctx, &grp);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_request_header_with_correlation_values(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[280] = {
        0x42, 0x00, 0x77, 0x01, 0x00, 0x00, 0x01, 0x10, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x50, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x05, 0x07, 0x00, 0x00, 0x00, 0x08,
        0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x31,
        0x42, 0x01, 0x06, 0x07, 0x00, 0x00, 0x00, 0x08,
        0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x31,
        0x42, 0x00, 0x07, 0x06, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
        0x42, 0x00, 0xD3, 0x06, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x40, 
        0x42, 0x00, 0x23, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x24, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x25, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x99, 0x07, 0x00, 0x00, 0x00, 0x06, 
        0x42, 0x61, 0x72, 0x6E, 0x65, 0x79, 0x00, 0x00, 
        0x42, 0x00, 0xA1, 0x07, 0x00, 0x00, 0x00, 0x07, 
        0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x32, 0x00, 
        0x42, 0x00, 0x0E, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x10, 0x06, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[280] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_4);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    struct text_string username = {0};
    username.value = "Barney";
    username.size = 6;
    struct text_string password = {0};
    password.value = "secret2";
    password.size = 7;
    
    struct username_password_credential upc = {0};
    upc.username = &username;
    upc.password = &password;
    
    struct credential c = {0};
    c.credential_type = KMIP_CRED_USERNAME_AND_PASSWORD;
    c.credential_value = &upc;
    
    struct authentication a = {0};
    a.credential = &c;
    
    enum attestation_type types[2] = {
        KMIP_ATTEST_TPM_QUOTE, 
        KMIP_ATTEST_SAML_ASSERTION
    };
    
    struct text_string ccv = {0};
    ccv.value = "client 1";
    ccv.size = 8;
    
    struct text_string scv = {0};
    scv.value = "server 1";
    scv.size = 8;
    
    struct request_header rh = {0};
    kmip_init_request_header(&rh);
    
    rh.protocol_version = &pv;
    rh.maximum_response_size = 4096;
    rh.asynchronous_indicator = KMIP_TRUE;
    rh.attestation_capable_indicator = KMIP_TRUE;
    rh.attestation_types = types;
    rh.attestation_type_count = ARRAY_LENGTH(types);
    rh.authentication = &a;
    rh.batch_error_continuation_option = KMIP_BATCH_CONTINUE;
    rh.batch_order_option = KMIP_TRUE;
    rh.batch_count = 2;
    
    rh.client_correlation_value = &ccv;
    rh.server_correlation_value = &scv;
    
    int result = kmip_encode_request_header(&ctx, &rh);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_response_header_with_correlation_values(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[184] = {
        0x42, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x00, 0xB0, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x4F, 0x9A, 0x54, 0xE5,
        0x42, 0x00, 0xC8, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x00, 0x04,
        0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x06,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x05, 0x07, 0x00, 0x00, 0x00, 0x08,
        0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x31,
        0x42, 0x01, 0x06, 0x07, 0x00, 0x00, 0x00, 0x08,
        0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x31, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[184] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_4);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    uint8 id[4] = {0x01, 0x02, 0x03, 0x04};
    struct byte_string ni = {0};
    ni.value = id;
    ni.size = ARRAY_LENGTH(id);
    
    uint8 value[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    struct byte_string nv = {0};
    nv.value = value;
    nv.size = ARRAY_LENGTH(value);
    
    struct nonce n = {0};
    n.nonce_id = &ni;
    n.nonce_value = &nv;
    
    enum attestation_type types[2] = {
        KMIP_ATTEST_TPM_QUOTE,
        KMIP_ATTEST_SAML_ASSERTION
    };
    
    struct text_string ccv = {0};
    ccv.value = "client 1";
    ccv.size = 8;
    
    struct text_string scv = {0};
    scv.value = "server 1";
    scv.size = 8;
    
    struct response_header rh = {0};
    kmip_init_response_header(&rh);
    
    rh.protocol_version = &pv;
    rh.time_stamp = 1335514341;
    rh.nonce = &n;
    rh.attestation_types = types;
    rh.attestation_type_count = ARRAY_LENGTH(types);
    rh.batch_count = 1;
    
    rh.client_correlation_value = &ccv;
    rh.server_correlation_value = &scv;
    
    int result = kmip_encode_response_header(&ctx, &rh);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_response_header_with_correlation_values(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 encoding[184] = {
        0x42, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x00, 0xB0, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x4F, 0x9A, 0x54, 0xE5,
        0x42, 0x00, 0xC8, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x00, 0x04,
        0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x06,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x05, 0x07, 0x00, 0x00, 0x00, 0x08,
        0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x31,
        0x42, 0x01, 0x06, 0x07, 0x00, 0x00, 0x00, 0x08,
        0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x31, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    
    struct kmip ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_1_4);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 0;
    
    uint8 id[4] = {0x01, 0x02, 0x03, 0x04};
    struct byte_string ni = {0};
    ni.value = id;
    ni.size = ARRAY_LENGTH(id);
    
    uint8 value[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    struct byte_string nv = {0};
    nv.value = value;
    nv.size = ARRAY_LENGTH(value);
    
    struct nonce n = {0};
    n.nonce_id = &ni;
    n.nonce_value = &nv;
    
    enum attestation_type types[2] = {
        KMIP_ATTEST_TPM_QUOTE,
        KMIP_ATTEST_SAML_ASSERTION
    };
    
    struct text_string ccv = {0};
    ccv.value = "client 1";
    ccv.size = 8;
    
    struct text_string scv = {0};
    scv.value = "server 1";
    scv.size = 8;
    
    struct response_header expected = {0};
    kmip_init_response_header(&expected);
    
    expected.protocol_version = &pv;
    expected.time_stamp = 1335514341;
    expected.nonce = &n;
    expected.attestation_types = types;
    expected.attestation_type_count = ARRAY_LENGTH(types);
    expected.batch_count = 1;
    
    expected.client_correlation_value = &ccv;
    expected.server_correlation_value = &scv;
    
    struct response_header observed = {0};
    kmip_init_response_header(&observed);
    
    int result = kmip_decode_response_header(&ctx, &observed);
    result = report_decoding_test_result(
        tracker,
        &ctx,
        kmip_compare_response_header(&expected, &observed),
        result,
        __func__);
    kmip_free_response_header(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

int
test_encode_response_header_kmip_2_0(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following set of values:
    *  Response Header
    *      Protocol Version
    *          Protocol Version Major - 2
    *          Protocol Version Minor - 0
    *      Time Stamp - 1335514341
    *      Nonce
    *          Nonce ID - 0x01020304
    *          Nonce Value - 0xFFFFFFFFFFFF
    *      Server Hashed Password - 301EC144E9C6C4F64C29C01C3E11839C97D6E7D2BC0C5DBC68377B679AE51D4D
    *      Attestation Type - TPM Quote
    *      Attestation Type - SAML Assertion
    *      Client Correlation Value - client 1
    *      Server Correlation Value - server 1
    *      Batch Count - 1
    */
    uint8 expected[224] = {
        0x42, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x00, 0xD8,
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x4F, 0x9A, 0x54, 0xE5,
        0x42, 0x00, 0xC8, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x00, 0x04,
        0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x06,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
        0x42, 0x01, 0x55, 0x08, 0x00, 0x00, 0x00, 0x20,
        0x30, 0x1E, 0xC1, 0x44, 0xE9, 0xC6, 0xC4, 0xF6,
        0x4C, 0x29, 0xC0, 0x1C, 0x3E, 0x11, 0x83, 0x9C,
        0x97, 0xD6, 0xE7, 0xD2, 0xBC, 0x0C, 0x5D, 0xBC,
        0x68, 0x37, 0x7B, 0x67, 0x9A, 0xE5, 0x1D, 0x4D,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x05, 0x07, 0x00, 0x00, 0x00, 0x08,
        0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x31,
        0x42, 0x01, 0x06, 0x07, 0x00, 0x00, 0x00, 0x08,
        0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x31,
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };

    uint8 observed[224] = {0};
    KMIP ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_2_0);

    ProtocolVersion pv = {0};
    pv.major = 2;
    pv.minor = 0;

    uint8 id[4] = {0x01, 0x02, 0x03, 0x04};
    ByteString ni = {0};
    ni.value = id;
    ni.size = ARRAY_LENGTH(id);

    uint8 value[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    ByteString nv = {0};
    nv.value = value;
    nv.size = ARRAY_LENGTH(value);

    Nonce n = {0};
    n.nonce_id = &ni;
    n.nonce_value = &nv;

    uint8 hash[32] = {
        0x30, 0x1E, 0xC1, 0x44, 0xE9, 0xC6, 0xC4, 0xF6,
        0x4C, 0x29, 0xC0, 0x1C, 0x3E, 0x11, 0x83, 0x9C,
        0x97, 0xD6, 0xE7, 0xD2, 0xBC, 0x0C, 0x5D, 0xBC,
        0x68, 0x37, 0x7B, 0x67, 0x9A, 0xE5, 0x1D, 0x4D
    };
    ByteString shp = {0};
    shp.value = hash;
    shp.size = ARRAY_LENGTH(hash);

    enum attestation_type types[2] = {
        KMIP_ATTEST_TPM_QUOTE,
        KMIP_ATTEST_SAML_ASSERTION
    };

    TextString ccv = {0};
    ccv.value = "client 1";
    ccv.size = 8;

    TextString scv = {0};
    scv.value = "server 1";
    scv.size = 8;

    ResponseHeader rh = {0};
    kmip_init_response_header(&rh);

    rh.protocol_version = &pv;
    rh.time_stamp = 1335514341;
    rh.nonce = &n;
    rh.server_hashed_password = &shp;
    rh.attestation_types = types;
    rh.attestation_type_count = ARRAY_LENGTH(types);
    rh.batch_count = 1;

    rh.client_correlation_value = &ccv;
    rh.server_correlation_value = &scv;

    int result = kmip_encode_response_header(&ctx, &rh);
    result = report_encoding_test_result(tracker, &ctx, expected, observed, result, __func__);

    kmip_destroy(&ctx);
    return(result);
}

int
test_decode_response_header_kmip_2_0(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* This encoding matches the following set of values:
    *  Response Header
    *      Protocol Version
    *          Protocol Version Major - 2
    *          Protocol Version Minor - 0
    *      Time Stamp - 1335514341
    *      Nonce
    *          Nonce ID - 0x01020304
    *          Nonce Value - 0xFFFFFFFFFFFF
    *      Server Hashed Password - 301EC144E9C6C4F64C29C01C3E11839C97D6E7D2BC0C5DBC68377B679AE51D4D
    *      Attestation Type - TPM Quote
    *      Attestation Type - SAML Assertion
    *      Client Correlation Value - client 1
    *      Server Correlation Value - server 1
    *      Batch Count - 1
    */
    uint8 encoding[224] = {
        0x42, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x00, 0xD8,
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00, 0x4F, 0x9A, 0x54, 0xE5,
        0x42, 0x00, 0xC8, 0x01, 0x00, 0x00, 0x00, 0x20,
        0x42, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x00, 0x04,
        0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x06,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
        0x42, 0x01, 0x55, 0x08, 0x00, 0x00, 0x00, 0x20,
        0x30, 0x1E, 0xC1, 0x44, 0xE9, 0xC6, 0xC4, 0xF6,
        0x4C, 0x29, 0xC0, 0x1C, 0x3E, 0x11, 0x83, 0x9C,
        0x97, 0xD6, 0xE7, 0xD2, 0xBC, 0x0C, 0x5D, 0xBC,
        0x68, 0x37, 0x7B, 0x67, 0x9A, 0xE5, 0x1D, 0x4D,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x01, 0x05, 0x07, 0x00, 0x00, 0x00, 0x08,
        0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x31,
        0x42, 0x01, 0x06, 0x07, 0x00, 0x00, 0x00, 0x08,
        0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x31,
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
    };

    KMIP ctx = {0};
    kmip_init(&ctx, encoding, ARRAY_LENGTH(encoding), KMIP_2_0);

    ProtocolVersion pv = {0};
    pv.major = 2;
    pv.minor = 0;

    uint8 id[4] = {0x01, 0x02, 0x03, 0x04};
    ByteString ni = {0};
    ni.value = id;
    ni.size = ARRAY_LENGTH(id);

    uint8 value[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    ByteString nv = {0};
    nv.value = value;
    nv.size = ARRAY_LENGTH(value);

    Nonce n = {0};
    n.nonce_id = &ni;
    n.nonce_value = &nv;

    uint8 hash[32] = {
        0x30, 0x1E, 0xC1, 0x44, 0xE9, 0xC6, 0xC4, 0xF6,
        0x4C, 0x29, 0xC0, 0x1C, 0x3E, 0x11, 0x83, 0x9C,
        0x97, 0xD6, 0xE7, 0xD2, 0xBC, 0x0C, 0x5D, 0xBC,
        0x68, 0x37, 0x7B, 0x67, 0x9A, 0xE5, 0x1D, 0x4D
    };
    ByteString shp = {0};
    shp.value = hash;
    shp.size = ARRAY_LENGTH(hash);

    enum attestation_type types[2] = {
        KMIP_ATTEST_TPM_QUOTE,
        KMIP_ATTEST_SAML_ASSERTION
    };

    TextString ccv = {0};
    ccv.value = "client 1";
    ccv.size = 8;

    TextString scv = {0};
    scv.value = "server 1";
    scv.size = 8;

    ResponseHeader expected = {0};
    kmip_init_response_header(&expected);

    expected.protocol_version = &pv;
    expected.time_stamp = 1335514341;
    expected.nonce = &n;
    expected.server_hashed_password = &shp;
    expected.attestation_types = types;
    expected.attestation_type_count = ARRAY_LENGTH(types);
    expected.batch_count = 1;

    expected.client_correlation_value = &ccv;
    expected.server_correlation_value = &scv;

    ResponseHeader observed = {0};
    kmip_init_response_header(&observed);

    int result = kmip_decode_response_header(&ctx, &observed);
    int comparison = kmip_compare_response_header(&expected, &observed);
    if(!comparison)
    {
        /* TODO (ph) Reorder these with printing result so that objects are
                     below function name.
        */
        kmip_print_response_header(1, &expected);
        kmip_print_response_header(1, &observed);
    }
    result = report_decoding_test_result(tracker, &ctx, comparison, result, __func__);

    kmip_free_response_header(&ctx, &observed);
    kmip_destroy(&ctx);
    return(result);
}

/*
The following tests are taken verbatim from the KMIP 1.1 Test Cases
documentation, available here:

http://docs.oasis-open.org/kmip/testcases/v1.1/kmip-testcases-v1.1.html
*/

int
test_kmip_1_1_test_suite_3_1_1_0_a(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* KMIP 1.1 Test Suite - Test 3.1.1.0a */
    uint8 expected[296] = {
        0x42, 0x00, 0x78, 0x01, 0x00, 0x00, 0x01, 0x20, 
        0x42, 0x00, 0x77, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0xD8, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0xC0, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x91, 0x01, 0x00, 0x00, 0x00, 0xA8, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x17, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x6C, 
        0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 
        0x42, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x14, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x4C, 0x65, 
        0x6E, 0x67, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x18, 
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x55, 0x73, 
        0x61, 0x67, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x6B, 
        0x42, 0x00, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[296] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_1);
    
    /* TODO (ph) If protocol version omitted, pull from context? */
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 1;
    
    struct request_header rh = {0};
    kmip_init_request_header(&rh);
    
    rh.protocol_version = &pv;
    rh.batch_count = 1;
    
    struct attribute a[3] = {{0}};
    for(int i = 0; i < 3; i++)
    {
        kmip_init_attribute(&a[i]);
    }
    
    enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES;
    a[0].type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM;
    a[0].value = &algorithm;
    
    int32 length = 128;
    a[1].type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH;
    a[1].value = &length;
    
    int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT;
    a[2].type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK;
    a[2].value = &mask;
    
    struct template_attribute ta = {0};
    ta.attributes = a;
    ta.attribute_count = ARRAY_LENGTH(a);
    
    struct create_request_payload crp = {0};
    crp.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    crp.template_attribute = &ta;
    
    struct request_batch_item rbi = {0};
    kmip_init_request_batch_item(&rbi);
    rbi.operation = KMIP_OP_CREATE;
    rbi.request_payload = &crp;
    
    struct request_message rm = {0};
    rm.request_header = &rh;
    rm.batch_items = &rbi;
    rm.batch_count = 1;
    
    int result = kmip_encode_request_message(&ctx, &rm);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_kmip_1_1_test_suite_3_1_1_0_b(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* KMIP 1.1 Test Suite - Test 3.1.1.0b */
    uint8 expected[200] = {
        0x42, 0x00, 0x7B, 0x01, 0x00, 0x00, 0x00, 0xC0, 
        0x42, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x4F, 0x9A, 0x54, 0xE5, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x68, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x7F, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x40, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x66, 0x62, 0x34, 0x62, 0x35, 0x62, 0x39, 0x63, 
        0x2D, 0x36, 0x31, 0x38, 0x38, 0x2D, 0x34, 0x63, 
        0x36, 0x33, 0x2D, 0x38, 0x31, 0x34, 0x32, 0x2D, 
        0x66, 0x65, 0x39, 0x63, 0x33, 0x32, 0x38, 0x31, 
        0x32, 0x39, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[200] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_0);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 1;
    
    struct response_header rh = {0};
    kmip_init_response_header(&rh);
    
    rh.protocol_version = &pv;
    rh.time_stamp = 1335514341;
    rh.batch_count = 1;
    
    struct text_string uuid = {0};
    uuid.value = "fb4b5b9c-6188-4c63-8142-fe9c328129fc";
    uuid.size = 36;
    
    struct create_response_payload crp = {0};
    crp.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    crp.unique_identifier = &uuid;
    
    struct response_batch_item rbi = {0};
    rbi.operation = KMIP_OP_CREATE;
    rbi.result_status = KMIP_STATUS_SUCCESS;
    rbi.response_payload = &crp;
    
    struct response_message rm = {0};
    rm.response_header = &rh;
    rm.batch_items = &rbi;
    rm.batch_count = 1;
    
    int result = kmip_encode_response_message(&ctx, &rm);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_kmip_1_1_test_suite_3_1_1_1_a(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* KMIP 1.1 Test Suite - Test 3.1.1.1a */
    uint8 expected[152] = {
        0x42, 0x00, 0x78, 0x01, 0x00, 0x00, 0x00, 0x90, 
        0x42, 0x00, 0x77, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x66, 0x62, 0x34, 0x62, 0x35, 0x62, 0x39, 0x63, 
        0x2D, 0x36, 0x31, 0x38, 0x38, 0x2D, 0x34, 0x63, 
        0x36, 0x33, 0x2D, 0x38, 0x31, 0x34, 0x32, 0x2D, 
        0x66, 0x65, 0x39, 0x63, 0x33, 0x32, 0x38, 0x31, 
        0x32, 0x39, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[152] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_1);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 1;
    
    struct request_header rh = {0};
    kmip_init_request_header(&rh);
    
    rh.protocol_version = &pv;
    rh.batch_count = 1;
    
    struct text_string uuid = {0};
    uuid.value = "fb4b5b9c-6188-4c63-8142-fe9c328129fc";
    uuid.size = 36;
    
    struct destroy_request_payload drp = {0};
    drp.unique_identifier = &uuid;
    
    struct request_batch_item rbi = {0};
    kmip_init_request_batch_item(&rbi);
    rbi.operation = KMIP_OP_DESTROY;
    rbi.request_payload = &drp;
    
    struct request_message rm = {0};
    rm.request_header = &rh;
    rm.batch_items = &rbi;
    rm.batch_count = 1;
    
    int result = kmip_encode_request_message(&ctx, &rm);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_kmip_1_1_test_suite_3_1_1_1_b(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* KMIP 1.1 Test Suite - Test 3.1.1.1b */
    uint8 expected[184] = {
        0x42, 0x00, 0x7B, 0x01, 0x00, 0x00, 0x00, 0xB0, 
        0x42, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x4F, 0x9A, 0x54, 0xE5, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x58, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x7F, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x66, 0x62, 0x34, 0x62, 0x35, 0x62, 0x39, 0x63, 
        0x2D, 0x36, 0x31, 0x38, 0x38, 0x2D, 0x34, 0x63, 
        0x36, 0x33, 0x2D, 0x38, 0x31, 0x34, 0x32, 0x2D, 
        0x66, 0x65, 0x39, 0x63, 0x33, 0x32, 0x38, 0x31, 
        0x32, 0x39, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[184] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_1);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 1;
    
    struct response_header rh = {0};
    kmip_init_response_header(&rh);
    
    rh.protocol_version = &pv;
    rh.time_stamp = 1335514341;
    rh.batch_count = 1;
    
    struct text_string uuid = {0};
    uuid.value = "fb4b5b9c-6188-4c63-8142-fe9c328129fc";
    uuid.size = 36;
    
    struct destroy_response_payload drp = {0};
    drp.unique_identifier = &uuid;
    
    struct response_batch_item rbi = {0};
    rbi.operation = KMIP_OP_DESTROY;
    rbi.result_status = KMIP_STATUS_SUCCESS;
    rbi.response_payload = &drp;
    
    struct response_message rm = {0};
    rm.response_header = &rh;
    rm.batch_items = &rbi;
    rm.batch_count = 1;
    
    int result = kmip_encode_response_message(&ctx, &rm);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_kmip_1_1_test_suite_3_1_3_2_a(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    /* KMIP 1.1 Test Suite - Test 3.1.3.2a */
    uint8 expected[152] = {
        0x42, 0x00, 0x78, 0x01, 0x00, 0x00, 0x00, 0x90, 
        0x42, 0x00, 0x77, 0x01, 0x00, 0x00, 0x00, 0x38, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x30, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[152] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_1);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 1;
    
    struct request_header rh = {0};
    kmip_init_request_header(&rh);
    
    rh.protocol_version = &pv;
    rh.batch_count = 1;
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    struct get_request_payload grp = {0};
    grp.unique_identifier = &uuid;
    
    struct request_batch_item rbi = {0};
    kmip_init_request_batch_item(&rbi);
    rbi.operation = KMIP_OP_GET;
    rbi.request_payload = &grp;
    
    struct request_message rm = {0};
    rm.request_header = &rh;
    rm.batch_items = &rbi;
    rm.batch_count = 1;
    
    int result = kmip_encode_request_message(&ctx, &rm);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

int
test_kmip_1_1_test_suite_3_1_3_2_b(TestTracker *tracker)
{
    TRACK_TEST(tracker);

    uint8 expected[304] = {
        0x42, 0x00, 0x7B, 0x01, 0x00, 0x00, 0x01, 0x28, 
        0x42, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x00, 0x48, 
        0x42, 0x00, 0x69, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x6B, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 
        0x00, 0x00, 0x00, 0x00, 0x4F, 0x9A, 0x54, 0xE7, 
        0x42, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x42, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0xD0, 
        0x42, 0x00, 0x5C, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x7F, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0xA8, 
        0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x24, 
        0x34, 0x39, 0x61, 0x31, 0x63, 0x61, 0x38, 0x38, 
        0x2D, 0x36, 0x62, 0x65, 0x61, 0x2D, 0x34, 0x66, 
        0x62, 0x32, 0x2D, 0x62, 0x34, 0x35, 0x30, 0x2D, 
        0x37, 0x65, 0x35, 0x38, 0x38, 0x30, 0x32, 0x63, 
        0x33, 0x30, 0x33, 0x38, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x8F, 0x01, 0x00, 0x00, 0x00, 0x60, 
        0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x58, 
        0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x20, 
        0x42, 0x00, 0x43, 0x08, 0x00, 0x00, 0x00, 0x18, 
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8, 
        0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
        0x42, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x04, 
        0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x00
    };
    
    uint8 observed[304] = {0};
    struct kmip ctx = {0};
    kmip_init(&ctx, observed, ARRAY_LENGTH(observed), KMIP_1_1);
    
    struct protocol_version pv = {0};
    pv.major = 1;
    pv.minor = 1;
    
    struct response_header rh = {0};
    kmip_init_response_header(&rh);
    
    rh.protocol_version = &pv;
    rh.time_stamp = 1335514343;
    rh.batch_count = 1;
    
    struct text_string uuid = {0};
    uuid.value = "49a1ca88-6bea-4fb2-b450-7e58802c3038";
    uuid.size = 36;
    
    uint8 value[24] = {
        0x73, 0x67, 0x57, 0x80, 0x51, 0x01, 0x2A, 0x6D, 
        0x13, 0x4A, 0x85, 0x5E, 0x25, 0xC8, 0xCD, 0x5E, 
        0x4C, 0xA1, 0x31, 0x45, 0x57, 0x29, 0xD3, 0xC8
    };

    struct byte_string v = {0};
    v.value = value;
    v.size = ARRAY_LENGTH(value);
    
    struct key_value kv = {0};
    kv.key_material = &v;
    
    struct key_block kb = {0};
    kb.key_format_type = KMIP_KEYFORMAT_RAW;
    kb.key_value = &kv;
    kb.cryptographic_algorithm = KMIP_CRYPTOALG_TRIPLE_DES;
    kb.cryptographic_length = 168;
    
    struct symmetric_key key = {0};
    key.key_block = &kb;
    
    struct get_response_payload grp = {0};
    grp.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY;
    grp.unique_identifier = &uuid;
    grp.object = &key;
    
    struct response_batch_item rbi = {0};
    rbi.operation = KMIP_OP_GET;
    rbi.result_status = KMIP_STATUS_SUCCESS;
    rbi.response_payload = &grp;
    
    struct response_message rm = {0};
    rm.response_header = &rh;
    rm.batch_items = &rbi;
    rm.batch_count = 1;
    
    int result = kmip_encode_response_message(&ctx, &rm);
    result = report_encoding_test_result(
        tracker,
        &ctx,
        expected,
        observed,
        result,
        __func__);
    kmip_destroy(&ctx);
    return(result);
}

/* Test Harness */

int
run_tests(void)
{
    TestTracker tracker = {0};
    
    printf("Tests\n");
    printf("=====\n");
    
    printf("\nUtility Tests\n");
    printf("-------------\n");
    test_linked_list_pop(&tracker);
    test_linked_list_push(&tracker);
    test_linked_list_enqueue(&tracker);
    test_buffer_bytes_left(&tracker);
    test_peek_tag(&tracker);
    test_is_attribute_tag(&tracker);
    test_get_enum_string_index(&tracker);
    test_check_enum_value_protection_storage_masks(&tracker);
    test_init_protocol_version(&tracker);
    test_init_request_batch_item(&tracker);
    test_deep_copy_int32(&tracker);
    test_deep_copy_text_string(&tracker);
    test_deep_copy_name(&tracker);
    test_deep_copy_attribute(&tracker);

    printf("\nKMIP 1.0 Feature Tests\n");
    printf("----------------------\n");
    test_buffer_full_and_resize(&tracker);
    test_is_tag_next(&tracker);
    test_get_num_items_next(&tracker);
    test_get_num_items_next_with_partial_item(&tracker);
    test_get_num_items_next_with_mismatch_item(&tracker);
    test_get_num_items_next_with_no_matches(&tracker);
    test_get_num_items_next_with_non_structures(&tracker);
    
    printf("\n");
    test_decode_int8_be(&tracker);
    test_decode_int32_be(&tracker);
    test_decode_int64_be(&tracker);
    test_decode_integer(&tracker);
    test_decode_long(&tracker);
    test_decode_enum(&tracker);
    test_decode_bool(&tracker);
    test_decode_text_string(&tracker);
    test_decode_byte_string(&tracker);
    test_decode_date_time(&tracker);
    test_decode_interval(&tracker);
    test_decode_name(&tracker);
    test_decode_attribute_unique_identifier(&tracker);
    test_decode_attribute_name(&tracker);
    test_decode_attribute_object_type(&tracker);
    test_decode_attribute_cryptographic_algorithm(&tracker);
    test_decode_attribute_cryptographic_length(&tracker);
    test_decode_attribute_operation_policy_name(&tracker);
    test_decode_attribute_cryptographic_usage_mask(&tracker);
    test_decode_attribute_state(&tracker);
    test_decode_template_attribute(&tracker);
    test_decode_protocol_version(&tracker);
    test_decode_key_material_byte_string(&tracker);
    test_decode_key_material_transparent_symmetric_key(&tracker);
    test_decode_key_value(&tracker);
    test_decode_key_value_with_attributes(&tracker);
    test_decode_cryptographic_parameters(&tracker);
    test_decode_encryption_key_information(&tracker);
    test_decode_mac_signature_key_information(&tracker);
    test_decode_key_wrapping_data(&tracker);
    test_decode_key_block_key_value_byte_string(&tracker);
    test_decode_key_block_key_value_structure(&tracker);
    test_decode_symmetric_key(&tracker);
    test_decode_public_key(&tracker);
    test_decode_private_key(&tracker);
    test_decode_key_wrapping_specification(&tracker);
    test_decode_create_request_payload(&tracker);
    test_decode_create_response_payload(&tracker);
    test_decode_create_response_payload_with_template_attribute(&tracker);
    test_decode_get_request_payload(&tracker);
    test_decode_get_response_payload(&tracker);
    test_decode_destroy_request_payload(&tracker);
    test_decode_destroy_response_payload(&tracker);
    test_decode_response_batch_item_get_payload(&tracker);
    test_decode_username_password_credential(&tracker);
    test_decode_credential_username_password_credential(&tracker);
    test_decode_authentication_username_password_credential(&tracker);
    test_decode_request_header(&tracker);
    test_decode_response_header(&tracker);
    test_decode_request_batch_item_get_payload(&tracker);
    test_decode_request_message_get(&tracker);
    test_decode_response_message_get(&tracker);
    
    printf("\n");
    test_encode_integer(&tracker);
    test_encode_long(&tracker);
    test_encode_enum(&tracker);
    test_encode_bool(&tracker);
    test_encode_text_string(&tracker);
    test_encode_byte_string(&tracker);
    test_encode_date_time(&tracker);
    test_encode_interval(&tracker);
    test_encode_name(&tracker);
    test_encode_attribute_unique_identifier(&tracker);
    test_encode_attribute_name(&tracker);
    test_encode_attribute_object_type(&tracker);
    test_encode_attribute_cryptographic_algorithm(&tracker);
    test_encode_attribute_cryptographic_length(&tracker);
    test_encode_attribute_operation_policy_name(&tracker);
    test_encode_attribute_cryptographic_usage_mask(&tracker);
    test_encode_attribute_state(&tracker);
    test_encode_protocol_version(&tracker);
    test_encode_cryptographic_parameters(&tracker);
    test_encode_encryption_key_information(&tracker);
    test_encode_mac_signature_key_information(&tracker);
    test_encode_key_wrapping_data(&tracker);
    test_encode_key_material_byte_string(&tracker);
    test_encode_key_material_transparent_symmetric_key(&tracker);
    test_encode_key_value(&tracker);
    test_encode_key_value_with_attributes(&tracker);
    test_encode_key_block_key_value_byte_string(&tracker);
    test_encode_key_block_key_value_structure(&tracker);
    test_encode_symmetric_key(&tracker);
    test_encode_public_key(&tracker);
    test_encode_private_key(&tracker);
    test_encode_key_wrapping_specification(&tracker);
    test_encode_create_request_payload(&tracker);
    test_encode_create_response_payload(&tracker);
    test_encode_create_response_payload_with_template_attribute(&tracker);
    test_encode_get_request_payload(&tracker);
    test_encode_get_request_payload_with_format_compression(&tracker);
    test_encode_get_request_payload_with_wrapping_spec(&tracker);
    test_encode_get_response_payload(&tracker);
    test_encode_destroy_request_payload(&tracker);
    test_encode_destroy_response_payload(&tracker);
    test_encode_username_password_credential(&tracker);
    test_encode_credential_username_password_credential(&tracker);
    test_encode_authentication_username_password_credential(&tracker);
    test_encode_request_header(&tracker);
    test_encode_response_header(&tracker);
    test_encode_request_batch_item_get_payload(&tracker);
    test_encode_response_batch_item_get_payload(&tracker);
    test_encode_request_message_get(&tracker);
    test_encode_response_message_get(&tracker);
    test_encode_template_attribute(&tracker);
    
    printf("\nKMIP 1.1 Feature Tests\n");
    printf("----------------------\n");
    test_decode_device_credential(&tracker);
    test_decode_key_wrapping_data_with_encoding_option(&tracker);
    
    printf("\n");
    test_encode_device_credential(&tracker);
    test_encode_key_wrapping_data_with_encoding_option(&tracker);
    test_encode_key_wrapping_specification_with_encoding_option(&tracker);
    
    printf("\nKMIP 1.1 Test Suite Test Cases\n");
    printf("------------------------------\n");
    test_kmip_1_1_test_suite_3_1_1_0_a(&tracker);
    test_kmip_1_1_test_suite_3_1_1_0_b(&tracker);
    test_kmip_1_1_test_suite_3_1_1_1_a(&tracker);
    test_kmip_1_1_test_suite_3_1_1_1_b(&tracker);
    test_kmip_1_1_test_suite_3_1_3_2_a(&tracker);
    test_kmip_1_1_test_suite_3_1_3_2_b(&tracker);
    
    printf("\nKMIP 1.2 Feature Tests\n");
    printf("----------------------\n");
    test_decode_nonce(&tracker);
    test_decode_attestation_credential(&tracker);
    test_decode_response_header_with_attestation_details(&tracker);
    test_decode_cryptographic_parameters_with_digital_signature_fields(&tracker);
    
    printf("\n");
    test_encode_nonce(&tracker);
    test_encode_attestation_credential(&tracker);
    test_encode_request_header_with_attestation_details(&tracker);
    test_encode_response_header_with_attestation_details(&tracker);
    test_encode_cryptographic_parameters_with_digital_signature_fields(&tracker);
    
    printf("\nKMIP 1.4 Feature Tests\n");
    printf("----------------------\n");
    test_decode_cryptographic_parameters_with_mask_fields(&tracker);
    test_decode_response_header_with_correlation_values(&tracker);
    
    printf("\n");
    test_encode_cryptographic_parameters_with_mask_fields(&tracker);
    test_encode_get_request_payload_with_wrap_type(&tracker);
    test_encode_request_header_with_correlation_values(&tracker);
    test_encode_response_header_with_correlation_values(&tracker);
    
    printf("\nKMIP 2.0 Feature Tests\n");
    printf("----------------------\n");
    test_decode_protection_storage_masks(&tracker);
    test_decode_attributes(&tracker);
    test_decode_attributes_with_invalid_kmip_version(&tracker);
    test_decode_attribute_v2_unique_identifier(&tracker);
    test_decode_attribute_v2_name(&tracker);
    test_decode_attribute_v2_object_type(&tracker);
    test_decode_attribute_v2_cryptographic_algorithm(&tracker);
    test_decode_attribute_v2_cryptographic_length(&tracker);
    test_decode_attribute_v2_cryptographic_usage_mask(&tracker);
    test_decode_attribute_v2_state(&tracker);
    test_decode_attribute_v2_unsupported_attribute(&tracker);
    test_decode_create_request_payload_kmip_2_0(&tracker);
    test_decode_request_batch_item_get_payload_kmip_2_0(&tracker);
    test_decode_response_header_kmip_2_0(&tracker);

    printf("\n");
    test_encode_protection_storage_masks(&tracker);
    test_encode_attributes(&tracker);
    test_encode_attributes_with_invalid_kmip_version(&tracker);
    test_encode_attribute_v2_unique_identifier(&tracker);
    test_encode_attribute_v2_name(&tracker);
    test_encode_attribute_v2_object_type(&tracker);
    test_encode_attribute_v2_cryptographic_algorithm(&tracker);
    test_encode_attribute_v2_cryptographic_length(&tracker);
    test_encode_attribute_v2_cryptographic_usage_mask(&tracker);
    test_encode_attribute_v2_state(&tracker);
    test_encode_attribute_v2_unsupported_attribute(&tracker);
    test_encode_create_request_payload_kmip_2_0(&tracker);
    test_encode_request_batch_item_get_payload_kmip_2_0(&tracker);
    test_encode_response_header_kmip_2_0(&tracker);

    printf("\nSummary\n");
    printf("================\n");
    printf("Total tests: %u\n", tracker.test_count);
    printf("       PASS: %u\n", tracker.tests_passed);
    printf("    FAILURE: %u\n", tracker.tests_failed);

    return(tracker.tests_failed);
}

void
print_help(const char *app)
{
    printf("Usage: %s [flag] ...\n\n", app);
    printf("Flags:\n");
    printf("-h : print this help info\n");
    printf("-i : run the test suite forever\n");
}

int
parse_arguments(int argc,
                char **argv,
                int *print_usage,
                int *run_forever)
{
    for(int i = 1; i < argc; i++)
    {
        if(strncmp(argv[i], "-h", 2) == 0)
        {
            *print_usage = 1;
        }
        else if(strncmp(argv[i], "-i", 2) == 0)
        {
            *run_forever = 1;
        }
        else
        {
            printf("Invalid option: '%s'\n", argv[i]);
            print_help(argv[0]);
            return(-1);
        }
    }
    
    return(0);
}

int
main(int argc, char **argv)
{
    int print_usage = 0;
    int run_forever = 0;
    
    int error = parse_arguments(argc, argv, &print_usage, &run_forever);
    if(error)
    {
        return(error);
    }
    if(print_usage)
    {
        print_help(argv[0]);
        return(0);
    }
    
    int results = 0;
    if(run_forever)
    {
        while(1)
        {
            run_tests();
        }
    }
    else
    {
        results = run_tests();
    }

    return(results);
}
